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/4PkHW9dSbQicKcempBoD3VCe2xQhJidJ6gptXPNvq4LVRBzJYAQrN5AGcaVfu88NabrczkgV8FrF4x1sVxKB7xSH
Gill 是一个新的 JavaScript 客户端库,用于与 Solana 区块链交互。在这篇文章中,我们讨论了 Gill 是什么、为什么它对 Solana 开发者很重要,以及它如何帮助改善开发者体验。我们还探讨了它的关键特性,提供了将其与 Web3.js v2 进行比较的示例,并演示了如何使用 Gill 创建和铸造 SPL Token。
总的来说,你会发现 Gill 在使用 Web3.js v2 时提供了出色的开发者体验。
- 原文链接: dev.to/shivamsspirit/int...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!