gill

Installation

Get started with gill, the new JavaScript client for Solana developers.

Gill is a modern javascript/typescript client library for interacting with the Solana blockchain. You can use it to build Solana apps in NodeJS, web browsers, React Native, and just about any other JavaScript environment.

Gill is built on top of the Solana JavaScript libraries built by Anza: @solana/kit (formerly known as "web3.js v2"). By utilizing the same types and functions under the hood, gill is compatible with @solana/kit. All @solana/kit imports can even be directly replaced with gill for one-to-one compatibility, plus unlocking the various quality-of-life improvements that gill provides.

Install gill

Install the core gill library in your project:

npm install gill

Coming from Kit?

All imports from the @solana/kit library can be directly replaces with gill to achieve the exact same functionality. Plus unlock the additional functionality only included in gill, like createTransaction.

Quick start

After installing gill, follow these simple steps to install and get started with the gill library:

Create a Solana RPC connection

Create a Solana rpc and rpcSubscriptions client connection from any RPC URL or standard Solana network moniker (i.e. devnet, localnet, mainnet etc).

import { createSolanaClient } from "gill";
 
const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = createSolanaClient({
  urlOrMoniker: "mainnet",
});

The above snippet demonstrates how to use the public Solana RPC endpoints. These are great for quick local testing, but they are (rightfully) subject to heavy rate limits.

When you are ready to ship your application to production, you will need to utilize a production ready RPC provider.

import { createSolanaClient } from "gill";
 
const { rpc, rpcSubscriptions, sendAndConfirmTransaction } = createSolanaClient({
  urlOrMoniker: "https://private-solana-rpc-provider.com",
});

Make Solana RPC requests

After you have a Solana rpc connection, you can make all the JSON RPC method calls directly off of it.

import { createSolanaClient } from "gill";
 
const { rpc } = createSolanaClient({ urlOrMoniker: "devnet" });
 
// get slot
const slot = await rpc.getSlot().send();
 
// get the latest blockhash
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();

The rpc client requires you to call .send() on the RPC method in order to actually send the request to your RPC provider and get a response.

Create a transaction

You can easily create transactions using the createTransaction() function. It accepts a single object argument that is fully typed for all the required (and optional) pieces of a Solana transaction.

When creating a Solana transaction, you will need several pieces of information:

  • version - legacy works well for every task, unless you need Address Lookup Tables (then use 0)
  • latest blockhash - This is like a recent timestamp check that the blockchain uses. Simply request it from your rpc.
  • instructions - Instructs the Solana runtime which programs and logic to execute onchain.
  • fee payer - The signer that will cover the small fee collected by the network to execute the transaction.

For simplicity, the following examples utilize loadKeypairSignerFromFile() to load a Solana keypair file from the local file system. Specifically the Solana CLI's default file path: ~/.config/solana/id.json. This can work well for running local scripts, but not for frontend applications where users will need to sign using their wallets. See Creating a signer without a secret key for details.

import { ,  } from "gill";
import {  } from "gill/node";
import {  } from "gill/programs";
 
/**
 * load the Solana CLI's default keypair file (`~/.config/solana/id.json`)
 * as a signer into your script
 */
const  = await ();
 
const {  } = ({ : "devnet" });
const { :  } = await .().();
 
const  = ({
  : "legacy", // or `0` if using address lookup tables
  : ,
  : [
    ({
      : "gm world!",
    }),
  ],
  ,
  // computeUnitLimit, // optional, but highly recommend to set
  // computeUnitPrice, // optional, but highly recommend to set
});

In the example above, we are loading a signer from the local file system to act as our fee payer and only signer. The transaction itself has a single "memo instruction" in it to log a simple message onchain.

You can now sign the transaction and send it to the blockchain for confirmation.

Optimizing transactions

You can (and should) optimize your Solana transactions by including a compute unit limit and compute unit price instructions within your transaction. The createTransaction() function supports easily adding these instructions via the computeUnitLimit and computeUnitPrice arguments.

Signing transactions

Once you have a transaction that is ready to be signed, you can call signTransactionMessageWithSigners() to perform the signing operations with all the available signers. This function will also assert that the transaction is fully signed.

If your transaction cannot be fully signed at this time (because you only have some of the signers available and attached), you can call partiallySignTransactionMessageWithSigners() to partially sign the transaction. Then the remaining signatures can be added later.

import {
  ,
  ,
  ,
} from "gill";
 
const { ,  } = ({
  : "devnet",
});
 
// ... [other business logic here]
 
const  = ({...});
 
const  = await ();
 
const  = getSignatureFromTransaction();

After a transaction has been signed by the feePayer, you can obtain its transaction signature using the getSignatureFromTransaction() function (yes, even before sending it to the network).

Once you have a fully signed transaction, signedTransaction in the example above, you can now send it to the blockchain network for confirmation.

Send and confirm transactions

When your transaction is ready and signed, you can send it to the network via your RPC provider using the sendAndConfirmTransaction() function initialized via gill's createSolanaClient():

import {
  ,
  ,
  ,
} from "gill";
 
const { ,  } = ({
  : "devnet",
});
 
// ... [other business logic here]
 
const  = ({...});
 
const  = await ();
 
const  = getSignatureFromTransaction();
 
try {
  .("Sending transaction:", );
 
  await ();
 
  .("Transaction confirmed!");
} catch () {
  .("Unable to send and confirm the transaction");
  .();
}

The sendAndConfirmTransaction() function performs a check to ensure all required signatures are present (aka the transactions is "fully signed") before attempting to send it to the network. If any signatures are missing, it will throw an error.

Congratulations! You now understand the basics of using the gill library to perform create and send Solana transactions.

Example source code

You can find the well-commented source code file for the above code snippets in gill's open source repo here: https://github.com/DecalLabs/gill/blob/master/examples/get-started/src/intro.ts

On this page