Marketplace has launched, further enabling blockchain developers! Learn more

How to Create a Fungible SPL token with the New Metaplex Token Standard

October 18, 2022

Overview

Are you creating a Whitelist token for your upcoming NFT mint? Or want to launch a fungible token for your next great dApp? Solana and Metaplex make it easy to do so right from your terminal! 

On June 20, 2022, Solana deprecated the Solana Token List, the repository which housed metadata with all fungible SPL tokens. The list has been replaced by Metaplex's Fungible Token Standard. If you're familiar with the old standard or just getting started with your first SPL token, this guide is for you. 

What You Will Do

In this guide, you will create a wallet (and airdrop some SOL), create fungible token metadata using the Metaplex standard, upload token metadata to Arweave, and mint a new fungible SPL token on Solana.

What You Will Need

* Nodejs installed (version 16.15 or higher)
* npm or yarn installed (We will be using yarn to initialize our project and install the necessary packages. Feel free to use npm instead if that’s your preferred package manager)
* Typescript experience and ts-node installed

Set Up Your Environment

Create a new project directory in your terminal with:

set up your environment

Copy
mkdir mint-fungible-spl
cd mint-fungible-spl

Create two files, wallet.ts and mint.ts. We will use wallet.ts to create a new dev wallet and airdrop some Solana for testing. We'll use mint.ts to mint a new SPL token and upload our token metadata. 

set up your environment

Copy
echo > {wallet,mint}.ts

Initialize your project with the "yes" flag to use default values for your new package: 

set up your environment

Copy
yarn init --yes
#or
npm init --yes

Create a tsconfig.json file: 

set up your environment

Copy
tsc --init

Open tsconfig.json and uncomment (or add) this to your file: 

set up your environment

Copy
"resolveJsonModule": true
This will allow us to import .json files into our repository, which will be important later when we want to generate a Keypair from a PrivateKey.

Also double check that esModuleInterop is set to true to allow for us to use imports. 

Install Solana Web3 dependencies:


set up your environment

Copy
yarn add @solana/web3.js @metaplex-foundation/mpl-token-metadata @metaplex-foundation/js @solana/spl-token
#or
npm install @solana/web3.js @metaplex-foundation/mpl-token-metadata @metaplex-foundation/js @solana/spl-token

Your environment should look something like this: 
Ready Solana Environment

Alright! We're all ready to go. 


Set Up Your Quicknode Endpoint

To build on Solana, you'll need an API endpoint to connect with the network. You're welcome to use public nodes or deploy and manage your own infrastructure; however, if you'd like 8x faster response times, you can leave the heavy lifting to us. See why over 50% of projects on Solana choose QuickNode and sign up for a free account here.
We're going to use a Solana Devnet node. Copy the HTTP Provider link:

New Solana Endpoint

Create a Wallet and Airdrop SOL

In order to mint a fungible SPL token, we'll first want to create a Devnet Wallet and airdrop SOL into it. Open wallet.ts and paste the following code in. We'll break it down in the next section.

create a wallet and airdrop sol

Copy
import { Keypair, LAMPORTS_PER_SOL, Connection } from "@solana/web3.js";
import * as fs from 'fs';

//STEP 1 - Connect to Solana Network
const endpoint = 'https://example.solana-devnet.quiknode.pro/000000/'; //Replace with your RPC Endpoint
const solanaConnection = new Connection(endpoint);

//STEP 2 - Generate a New Solana Wallet
const keypair = Keypair.generate();
console.log(`Generated new KeyPair. Wallet PublicKey: `, keypair.publicKey.toString());

//STEP 3 - Write Wallet Secret Key to a .JSON
const secret_array = keypair.secretKey    
    .toString() //convert secret key to string
    .split(',') //delimit string by commas and convert to an array of strings
    .map(value=>Number(value)); //convert string values to numbers inside the array

const secret = JSON.stringify(secret_array); //Covert to JSON string

fs.writeFile('guideSecret.json', secret, 'utf8', function(err) {
    if (err) throw err;
    console.log('Wrote secret key to guideSecret.json.');
    });

//STEP 4 - Airdrop 1 SOL to new wallet
(async()=>{
    const airdropSignature = solanaConnection.requestAirdrop(
        keypair.publicKey,
        LAMPORTS_PER_SOL,
    );
    try{
        const txId = await airdropSignature;     
        console.log(`Airdrop Transaction Id: ${txId}`);        
        console.log(`https://explorer.solana.com/tx/${txId}?cluster=devnet`)
    }
    catch(err){
        console.log(err);
    }    
})()

This script will perform 4 tasks: 
  1. Connect to the Solana Network (Make sure you replace endpoint with your Quicknode Endpoint URL that you saved in the previous step).
  2. Generate a new Wallet Keypair.
  3. Write the Secret Key to a .json file that we'll use in the next step. Lines 13-18 are necessary to format the key as an array of numbers. Lines 20-22 use fs to export the array to a .json file.
  4. Airdrop 1 SOL to the new Wallet. 

Go ahead and run this script to create a new wallet and aidrop it 1 SOL: 

create a wallet and airdrop sol

Copy
ts-node wallet.ts

You should see a new file, guideSecret.json in your project folder and a terminal log like this:

create a wallet and airdrop sol

Copy
Generated new KeyPair. Wallet PublicKey:  DQmULZZBnnyZeoYsMLaNmtY5ZgTk5LJtBmM1ApqbqWKe
Wrote secret key to guideSecret.json.
Airdrop Transaction Id: 3mqvvtHQbPyHrtEA6nQT9z7YtKbjP4YzjYE7xoMq7XG6WU8v6WouvUPiSFnUbBhtzX7c1SE859fXWbHPTSHXuu
https://explorer.solana.com/tx/3mqvvtHQbPyHrtEA6nQT9z7YtKbjP4YzjYE7xoMq7XG6WU8v6WouvUPiSFnUbBhtzX7c1SE859fXWbHPTSHXuu?cluster=devnet

Let's make our token!

Build a Mint Tool

Import Dependencies


Open up mint.ts and import the following dependencies on line 1

build a mint tool

Copy
import { Transaction, SystemProgram, Keypair, Connection, PublicKey } from "@solana/web3.js";
import { MINT_SIZE, TOKEN_PROGRAM_ID, createInitializeMintInstruction, getMinimumBalanceForRentExemptMint, getAssociatedTokenAddress, createAssociatedTokenAccountInstruction, createMintToInstruction } from '@solana/spl-token';
import { DataV2, createCreateMetadataAccountV2Instruction } from '@metaplex-foundation/mpl-token-metadata';
import { bundlrStorage, findMetadataPda, keypairIdentity, Metaplex, UploadMetadataInput } from '@metaplex-foundation/js';
import secret from './guideSecret.json';

We'll cover these as we get to them in the guide, but we do want to note that final import, secret, which is importing the .json we created in the previous step.

Establish Solana Connection


Create a Connection to the Solana network but pasting your adding your Quicknode Endpoint URL to the code below and pasting it just below your imports: 

build a mint tool

Copy
const endpoint = 'https://example.solana-devnet.quiknode.pro/000000/'; //Replace with your RPC Endpoint
const solanaConnection = new Connection(endpoint);

Create Mint Configuration and Metadata

Let's add some detail about the token we want to create. Below your Solana Connection, create a variable called MINT_CONFIG that we'll use to define the number of decimals our token will have and the number of tokens we'd like to mint: 

build a mint tool

Copy
const MINT_CONFIG = {
    numDecimals: 6,
    numberTokens: 1337
}
Note: setting numDecimals to 0 results in a token that cannot be subdivided. This might be relevant for something like a membership or whitelist mint token.

Now let's define our metadata. Solana has recently adopted Metaplex's Fungible Token Standard, which requires a name, symbol, description, and image (all are string values). Using the standard with your token mint will enable major platforms like Phantom Wallet or Solana Explorer to easily recognize your token and make it viewable by their users. 

After MINT_CONFIG, create a new object called MY_TOKEN_METADATA of type, UploadMetadataInput and define your token: 

build a mint tool

Copy
const MY_TOKEN_METADATA: UploadMetadataInput = {
    name: "Test Token",
    symbol: "TEST",
    description: "This is a test token!",
    image: "https://URL_TO_YOUR_IMAGE.png" //add public URL to image you'd like to use
}

Later in this excercise, we'll use Metaplex's uploadMetadata method to load this metadata to Arweave.

Finally, we'll need to create a second metadata variable that will be loading onto Solana into Metaplex's Program. Create a new variable, ON_CHAIN_METADATA

build a mint tool

Copy
const ON_CHAIN_METADATA = {
    name: MY_TOKEN_METADATA.name, 
    symbol: MY_TOKEN_METADATA.symbol,
    uri: 'TO_UPDATE_LATER',
    sellerFeeBasisPoints: 0,
    creators: null,
    collection: null,
    uses: null
} as DataV2;

You'll see that we use the name and symbol from MY_TOKEN_METADATA. We define a key, uri as a string that we'll update later. This will need to be replaced to a URL where we upload our MY_TOKEN_METADATA object. Set sellerFeeBasisPoints to 0 and set creators, collection, and uses to null since we won't need those for a fungible token.

Finally, create a function to upload MY_TOKEN_METADATA to Arweave. 

build a mint tool

Copy
/**
 * 
 * @param wallet Solana Keypair
 * @param tokenMetadata Metaplex Fungible Token Standard object 
 * @returns Arweave url for our metadata json file
 */
const uploadMetadata = async(wallet: Keypair, tokenMetadata: UploadMetadataInput):Promise<string> => {
    //create metaplex instance on devnet using this wallet
    const metaplex = Metaplex.make(solanaConnection)
        .use(keypairIdentity(wallet))
        .use(bundlrStorage({
        address: 'https://devnet.bundlr.network',
        providerUrl: endpoint,
        timeout: 60000,
        }));
    
    //Upload to Arweave
    const { uri } = await metaplex.nfts().uploadMetadata(tokenMetadata);
    console.log(`Arweave URL: `, uri);
    return uri;
}

Note: if you are using a version of Metaplex JS before 0.17, you may need to add .run() to the end of your uploadMetadata() call.

The upLoadMetadata function will do two things: 
1. Establish an instance of Metaplex on the devnet using Bundlr, which allows uploads to Arweave using SOL. The instance will use the RPC endpoint from earlier and the imported Keypair (to fund upload fees). 
2. Executes upload using uploadMetadata and returning an Arweave URL. 

Great! If you're following along, your code should look something like this: 

build a mint tool

Copy
import { Transaction, SystemProgram, Keypair, Connection, PublicKey } from "@solana/web3.js";
import { MINT_SIZE, TOKEN_PROGRAM_ID, createInitializeMintInstruction, getMinimumBalanceForRentExemptMint, getAssociatedTokenAddress, createAssociatedTokenAccountInstruction, createMintToInstruction } from '@solana/spl-token';
import { DataV2, createCreateMetadataAccountV2Instruction } from '@metaplex-foundation/mpl-token-metadata';
import { bundlrStorage, findMetadataPda, keypairIdentity, Metaplex, UploadMetadataInput } from '@metaplex-foundation/js';
import secret from './guideSecret.json';

const endpoint = 'https://example.solana-devnet.quiknode.pro/000000/'; //Replace with your RPC Endpoint
const solanaConnection = new Connection(endpoint);

const MINT_CONFIG = {
    numDecimals: 6,
    numberTokens: 1337
}

const MY_TOKEN_METADATA: UploadMetadataInput = {
    name: "Test Token",
    symbol: "TEST",
    description: "This is a test token!",
    image: "https://URL_TO_YOUR_IMAGE.png" //add public URL to image you'd like to use
}

const ON_CHAIN_METADATA = {
    name: MY_TOKEN_METADATA.name, 
    symbol: MY_TOKEN_METADATA.symbol,
    uri: 'TO_UPDATE_LATER',
    sellerFeeBasisPoints: 0,
    creators: null,
    collection: null,
    uses: null
} as DataV2;

/**
 * 
 * @param wallet Solana Keypair
 * @param tokenMetadata Metaplex Fungible Token Standard object 
 * @returns Arweave url for our metadata json file
 */
 const uploadMetadata = async(wallet: Keypair, tokenMetadata: UploadMetadataInput):Promise<string> => {
    //create metaplex instance on devnet using this wallet
    const metaplex = Metaplex.make(solanaConnection)
        .use(keypairIdentity(wallet))
        .use(bundlrStorage({
        address: 'https://devnet.bundlr.network',
        providerUrl: endpoint,
        timeout: 60000,
        }));
    
    //Upload to Arweave
    const { uri } = await metaplex.nfts().uploadMetadata(tokenMetadata);
    console.log(`Arweave URL: `, uri);
    return uri;
}

Assemble Mint Transaction

Now we need to create a function that will create a Solana Transaction for our Mint. We've modeled our transaction after Solana's demonstration site. This is pretty similar to minting an SPL token previously, but now requires an additional step of adding Metadata to the token.

After your uploadMetadata function, create a new function, createNewMintTransaction and pass in 6 parameters: connection, payer, mintKeypair, destinationWallet, mintAuthority, freezeAuthority:

build a mint tool

Copy
const createNewMintTransaction = async (connection:Connection, payer:Keypair, mintKeypair: Keypair, destinationWallet: PublicKey, mintAuthority: PublicKey, freezeAuthority: PublicKey)=>{

}

Note: if you want to use one wallet for payer, destination, mint authority, and freeze authority, you can use just the payer parameter, but we've separated this out in case you want to have different wallets serve different functions.

Inside our function, we'll need to get 3 values that will be necessary for our transaction: 
  1. Calculate number of lamports required for our Token Mint Account. Solana has a built in method for this, getMinimumBalanceForRentExemptMint
  2. Get the Metaplex program derived address ("PDA") for our token mint, using the Metaplex method, findMetadataPda
  3. Finally, we'll want to define our destination token address that we will pass into our createAssociatedTokenAccount instructions. We'll call our mint address and destination owner wallet into the Solana method, getAssociatedTokenAddress.

build a mint tool

Copy
    //Get the minimum lamport balance to create a new account and avoid rent payments
    const requiredBalance = await getMinimumBalanceForRentExemptMint(connection);
    //metadata account associated with mint
    const metadataPDA = await findMetadataPda(mintKeypair.publicKey);
    //get associated token account of your wallet
    const tokenATA = await getAssociatedTokenAddress(mintKeypair.publicKey, destinationWallet);   

Now let's create our Transactions. Solana allows you to append multiple transactions instructions to a single Transaction using .add().

Create a new variable, createNewTokenTransaction

build a mint tool

Copy
const createNewTokenTransaction = new Transaction().add(
)

For our new mint, we're going to be stringing together 5 sets of instructions (add each of these in sequence inside of the .add() in your createNewTokenTransaction variable): 

1. createAccount - Create new mint account. We must pass a CreateAccountParams into this instruction, which is an object comprised of fromPubKey (our account payer), newAccountPubkey (our new mint address), lamports (requiredBalance we calculated earlier will be transferred to the new account to avoid rent exemption), space (MINT_SIZE an import from spl-token library to ensure we allocate the correct amount of space to the new account), and programId (TOKEN_PROGRAM_ID imported from spl-token library).

build a mint tool

Copy
        SystemProgram.createAccount({
            fromPubkey: payer.publicKey,
            newAccountPubkey: mintKeypair.publicKey,
            space: MINT_SIZE,
            lamports: requiredBalance,
            programId: TOKEN_PROGRAM_ID,
        }),

2.createInitializeMintInstruction - Initialize the new mint account. Here we'll pass mint (our mint public key), decimals (number of decimals in our MINT_CONFIG), mintAuthority(our mintAuthority parameter), freezeAuthority (our freezeAuthority parameter), and programId (TOKEN_PROGRAM_ID imported from spl-token library). 

build a mint tool

Copy
        createInitializeMintInstruction(
          mintKeypair.publicKey, //Mint Address
          MINT_CONFIG.numDecimals, //Number of Decimals of New mint
          mintAuthority, //Mint Authority
          freezeAuthority, //Freeze Authority
          TOKEN_PROGRAM_ID),

3. createAssociatedTokenAccountInstruction - Create a new token account for the new mint in your destination wallet. We will pass payer from our parameters, associatedToken (the tokenATA variable we defined earlier, which will be the token account where our tokens will ultimately be deposited),  owner (the wallet owner of the new token account, our payer), and the mint (the public key of the mint we  created). 

build a mint tool

Copy
        createAssociatedTokenAccountInstruction(
          payer.publicKey, //Payer 
          tokenATA, //Associated token account 
          payer.publicKey, //Token account owner
          mintKeypair.publicKey, //Mint
        ),

4. createMintToInstruction - Instruction that will define what tokens to mint, where to mint them to, and how many to mint. We will pass mint (our mint public key), destination (the token account where the tokens should go, our tokenATA), authority (the authority that is able to mint new tokens for the mint--the same mintAuthority we defined in CreateInitializeMintInstruction above), and amount (number of tokens to mint--note that like lamports, we must pass the decimal value of our desired token amount by using Math.pow(10) and our MINT_CONFIG).

build a mint tool

Copy
        createMintToInstruction(
          mintKeypair.publicKey, //Mint
          tokenATA, //Destination Token Account
          mintAuthority, //Authority
          MINT_CONFIG.numberTokens * Math.pow(10, MINT_CONFIG.numDecimals),//number of tokens
        ),

5. createCreateMetadataAccountV2Instruction - associate our token meta data with this mint. We will pass CreateMetadataAccountV2InstructionAccounts, an object that includes metadata (the program derived address, metadataPDA that we've already defined), mint (public key of our mint), mintAuthority (the same authority set in createInitializeMintInstruction), payer (entity to cover transaction fees), updateAuthority (we'll use the same mintAuthority from our parameters). Then we must pass createMetadataAccountArgsV2 which includes data (this is the actual data that will be stored on chain, our ON_CHAIN_METADATA) and isMutable a boolean that sets whether or not you can change this metadata in the future. 

build a mint tool

Copy
        createCreateMetadataAccountV2Instruction({
            metadata: metadataPDA, 
            mint: mintKeypair.publicKey, 
            mintAuthority: mintAuthority,
            payer: payer.publicKey,
            updateAuthority: mintAuthority,
          },
          { createMetadataAccountArgsV2: 
            { 
              data: ON_CHAIN_METADATA, 
              isMutable: true 
            } 
          }
        )

Whew! That's a big transaction! After we create the transaction, we'll want our function to return it. Add a return to your transaction: 

build a mint tool

Copy
return createNewTokenTransaction;

Your final function should look something like this: 

build a mint tool

Copy
const createNewMintTransaction = async (connection:Connection, payer:Keypair, mintKeypair: Keypair, destinationWallet: PublicKey, mintAuthority: PublicKey, freezeAuthority: PublicKey)=>{
    //Get the minimum lamport balance to create a new account and avoid rent payments
    const requiredBalance = await getMinimumBalanceForRentExemptMint(connection);
    //metadata account associated with mint
    const metadataPDA = await findMetadataPda(mintKeypair.publicKey);
    //get associated token account of your wallet
    const tokenATA = await getAssociatedTokenAddress(mintKeypair.publicKey, destinationWallet);   
    

    const createNewTokenTransaction = new Transaction().add(
        SystemProgram.createAccount({
            fromPubkey: payer.publicKey,
            newAccountPubkey: mintKeypair.publicKey,
            space: MINT_SIZE,
            lamports: requiredBalance,
            programId: TOKEN_PROGRAM_ID,
        }),
        createInitializeMintInstruction(
          mintKeypair.publicKey, //Mint Address
          MINT_CONFIG.numDecimals, //Number of Decimals of New mint
          mintAuthority, //Mint Authority
          freezeAuthority, //Freeze Authority
          TOKEN_PROGRAM_ID),
        createAssociatedTokenAccountInstruction(
          payer.publicKey, //Payer 
          tokenATA, //Associated token account 
          payer.publicKey, //token owner
          mintKeypair.publicKey, //Mint
        ),
        createMintToInstruction(
          mintKeypair.publicKey, //Mint
          tokenATA, //Destination Token Account
          mintAuthority, //Authority
          MINT_CONFIG.numberTokens * Math.pow(10, MINT_CONFIG.numDecimals),//number of tokens
        ),
        createCreateMetadataAccountV2Instruction({
            metadata: metadataPDA, 
            mint: mintKeypair.publicKey, 
            mintAuthority: mintAuthority,
            payer: payer.publicKey,
            updateAuthority: mintAuthority,
          },
          { createMetadataAccountArgsV2: 
            { 
              data: ON_CHAIN_METADATA, 
              isMutable: true 
            } 
          }
        )
    );

    return createNewTokenTransaction;
}

Pull it All Together

Alright, you're almost done. We just need a function that pulls all of this together that we can execute in our app. Create a new async function called main with the following code: 

build a mint tool

Copy
const main = async() => {
    console.log(`---STEP 1: Uploading MetaData---`);
    const userWallet = Keypair.fromSecretKey(new Uint8Array(secret));
    let metadataUri = await uploadMetadata(userWallet, MY_TOKEN_METADATA);
    ON_CHAIN_METADATA.uri = metadataUri;

    console.log(`---STEP 2: Creating Mint Transaction---`);
    let mintKeypair = Keypair.generate();   
    console.log(`New Mint Address: `, mintKeypair.publicKey.toString());

    const newMintTransaction:Transaction = await createNewMintTransaction(
        solanaConnection,
        userWallet,
        mintKeypair,
        userWallet.publicKey,
        userWallet.publicKey,
        userWallet.publicKey
    );

    console.log(`---STEP 3: Executing Mint Transaction---`);
    const transactionId =  await solanaConnection.sendTransaction(newMintTransaction, [userWallet, mintKeypair]);
    console.log(`Transaction ID: `, transactionId);
    console.log(`Succesfully minted ${MINT_CONFIG.numberTokens} ${ON_CHAIN_METADATA.symbol} to ${userWallet.publicKey.toString()}.`);
    console.log(`View Transaction: https://explorer.solana.com/tx/${transactionId}?cluster=devnet`);
    console.log(`View Token Mint: https://explorer.solana.com/address/${mintKeypair.publicKey.toString()}?cluster=devnet`)
}

You'll see our main function has 3 steps:
1. Upload Metadata. We start by loading our secret from the .json we created earlier in this exercise to define a userWallet Keypair. We pass that wallet and MY_TOKEN_METADATA into Metaplex's uploadMetadata method to return an Arweave URI storing our metadata. We then set ON_CHAIN_METADATA.uri to that URI. 
2. Create our mint transaction. Start by creating a new keypair for our new mint account. Then, run our CreateNewMintTransaction function, passing in our solanaConnection, userWallet, mintKeypair, and userWallet.publicKey.
3. Finally, execute the transaction. Pass newMintTransaction into sendTransaction with userWallet and mintKeypair as signers. Log our results!

Run Your Code

Finally, call main on the final line of your code: 

run your code

Copy
main();

We've made our final code available here.  

In your Terminal, type: 

run your code

Copy
ts-node mint.ts

You should see step progression for each of our three steps and a final URL to the successful transaction: 
Final results terminal output

If you click the "View Token Mint" link in your terminal, you should be able to see your new Token on Solana Explorer! Here's ours:
New token mint - Solana explorer


Note: If you've minted a fungible token in the past, you've probably submitted your token to the Solana Token Program Registry. That registry is now deprecated and no longer a necessary step. You've already uploaded the metadata on chain, so you're good to go!

Party Time! 🎉

Congrats! You just minted your own token on Solana using the new Metaplex fungible token standard. Have some fun with this--we're excited to see what tokens you're creating! To learn more, check out some of our other Solana tutorials here

We ❤️ Feedback!
If you have any feedback or questions on this guide, let us know. Or, feel free to reach out to us via Twitter or our Discord community server. We’d love to hear from you! 

Related articles 33

Como crear un NFT en SOLANA
Published: Dec 27, 2021
Updated: Sep 23, 2022

¡Hola querido lector! Bienvenidos a una nueva guía de Solana.Solana es una blockchain que promete mucho a la hora de intentar resolver los problemas de escalabilidad que...

Continue reading
How to Get Transaction Logs on Solana
Published: Jun 24, 2022
Updated: Oct 27, 2022

Ever need to pull all the transactions associated with a Wallet? Want to see all of the mint transactions associated with a Candy Machine? Or maybe see transaction history of an NFT? Solana's...

Continue reading
How to Transfer SPL Tokens on Solana
Published: Sep 23, 2022
Updated: Sep 23, 2022

Sending Solana Program Library (SPL) Tokens is a critical mechanism for Solana development. Whether you are airdropping whitelist tokens to your community, bulk sending NFTs to another wallet,...

Continue reading
How to Mint an NFT on Solana
Published: Aug 27, 2021
Updated: Sep 23, 2022

Updated at: April 10, 2022Welcome to another QuickNode guide on Solana - the up-and-coming blockchain that seeks to solve the scalability issues of Ethereum. We will be walking through...

Continue reading
How to Send Bulk Transactions on Solana
Published: Aug 31, 2022
Updated: Oct 3, 2022

Are you running a batch process that has many transactions? Perhaps an airdrop to your community's NFT holders or a token distribution to early users of your dApp. Solana transaction...

Continue reading
Solana Fundamentals Reference Guide
Published: Oct 27, 2022
Updated: Oct 27, 2022

The Solana blockchain is a powerful tool, delivering thousands of transactions per second with almost no-cost transaction fees. If you are new to Web3 or have developed on EVM-based...

Continue reading