acheroncrypto/solutils

React Hooks and Helpers for Solana

★ 1Forks 0GitHub ↗Compare

README

solutils logo

React Hooks and Helpers for Solana


This library is still a WIP, so community help and feedback is more than welcome.

Summary

Solana Pay, and NFT helpers coming soon!


Cluster

getClusterConnection()

Definition

Establish a JSON RPC connection from a particular cluster (devnet, testnet or mainnet) and return a Connection object.

⚠️ WARNING: You shouldn't use this method if you're using @solana/wallet-adapter-react since you have this method in a hook form.

Example

import { getClusterConnection } from 'solutils';

const { connection } = getClusterConnection('devnet');

// Then trigger any API method from connection
connection.getSlot().then((slot) => console.log(slot));
getClusterName()

Definition

It returns a parsed name from your cluster name.

Example

import { getClusterName } from 'solutils';

const { clusterName } = getClusterName('mainnet-beta');

console.log(clusterName); // "Mainnet"

Keypairs

getNewKeypair()

Definition

It returns a new account keypair that could be used for testing purposes like signing transactions.

Example

import { getNewKeypair } from 'solutils';

const { keypair } = getNewKeypair();
getKeypairFromFile()

Definition

It returns a keypair by reading a secret key from a filepath, if not path is specified it will use defaults Solana path which is ~/.config/solana/id.json.

⚠️ WARNING: This method only works on a Node.js only environment.

Example

import { getNewKeypair } from 'solutils';

const { keypair } = getKeypairFromFile();
getKeypairFromSecretKey()

Definition

It returns an account keypair from a secret key, needed when you have a secret key but not the public key related.

Example

import { getKeypairFromSecretKey, getAddressFromPublicKey } from 'solutils';

const secretKey = [
  134, 98, 243, 255, 26, 77, 24, 179, 246, 4, 71, 250, 137, 117, 154, 223, 245, 56, 40, 129, 83, 9, 251, 155, 79, 73,
  35, 81, 189, 161, 49, 212, 155, 197, 139, 80, 211, 197, 3, 178, 85, 182, 49, 34, 74, 63, 90, 80, 117, 115, 67, 185,
  246, 42, 73, 93, 91, 12, 189, 113, 33, 171, 182, 60,
];

const { keypair } = getKeypairFromSecretKey(secretKey);
const { address } = getAddressFromPublicKey(keypair.publicKey);

console.log(address); // BV4uLAAaPtQSZRYrvwvFzn2fJJkinLQJb73mnhgPYfDM
getAddressFromPublicKey()

Definition

Returns an account address from a public key object.

Example

import { getNewKeypair, getAddressFromPublicKey } from 'solutils';

const { keypair } = getNewKeypair();
const { address } = getAddressFromPublicKey(keypair.publicKey);

console.log(address); // G9KwiPLZyC52zrSsHnbf9FPnuHu77CDAeGoVkSa1wS8R
getPublicKeyFromAddress()

Definition

Returns an account public key from an address string.

Example

import { getPublicKeyFromAddres } from 'solutils';

const address = 'G9KwiPLZyC52zrSsHnbf9FPnuHu77CDAeGoVkSa1wS8R';
const { publicKey } = getPublicKeyFromAddres(address);
getIsValidPublicKey()

Definition

Validates if a public key is correct or not.

Example

import { getNewKeypair, getIsValidPublicKey } from 'solutils';

const { keypair } = getNewKeypair();
const { isValid } = getIsValidPublicKey(keypair.publicKey);

console.log(isValid); // true
getShortAddress()

Definition

Returns a shorter string from your address.

Example

import { getShortAddress } from 'solutils';

const address = 'BV4uLAAaPtQSZRYrvwvFzn2fJJkinLQJb73mnhgPYfDM';
const { shortAddress } = getShortAddress(address);

console.log(shortAddress); // "BV4u...YfDM"

Units

getLamportsToSol()

Definition

Converts lamports units to SOL units. Optionally send a second argument to define amount of digits to truncate without rounding.

Example

import { getLamportsToSol } from 'solutils';

const { sol } = getLamportsToSol(3005000000);

console.log(sol); // 3.005
import { getLamportsToSol } from 'solutils';

const { sol } = getLamportsToSol(3345400000, 2);

console.log(sol); // 3.34
getSolToLamports()

Definition

Converts lamports units to SOL units.

Example

import { getSolToLamports } from 'solutils';

const { lamports } = getSolToLamports(2.5);

console.log(lamports); // 2500000000

URLs

getRpcEndpointUrl()

Definition

Returns a RPC endpoint by defining a provider and a cluster type.

Current supported RPC providers are: Solana, Project Serum, GenesysGo, AllThatNode, Blockdaemon, Ankr, GetBlock, and Alchemy. Being Alchemy the only one that needs an API key that will be received as a third parameter.

⚠️ WARNING: For production you probably want to get a paid RPC service due to service limitations.

Example

import { getRpcEndpointUrl } from 'solutils';

const { rpcEndpointUrl: solanaMainnetRpc } = getRpcEndpointUrl('solana', 'mainnet');
console.log(solanaMainnetRpc); // "https://api.mainnet-beta.solana.com"

const { rpcEndpointUrl: genesysGoRpc } = getRpcEndpointUrl('genesysgo', 'devnet');
console.log(genesysGoRpc); // "https://devnet.genesysgo.net"
getExplorerUrl()

Definition

Returns a Solana explorer url explorer type that could be Solana Explorer, Solscan, SolanaFM, or Solana Beach, and a transaction siganture, block or address. It automatically switches between a transaction, block, or address url parameter based on its length. By default uses Mainnet cluster, but optionally takes a cluster as third parameter.

Example

import { getExplorerUrl } from 'solutils';

const transactionSignature = '55oJv5oCaez344JawHL5gnwqwrbrN4oD5ZN8rQFvyRSWzwXTTe178QG7KK9cR2wFkwecEca3V5vdbFexFG1ayECm';
const { url: solanaExplorerUrl } = getExplorerUrl('solana-explorer', transactionSignature);
const { url: solscanUrl } = getExplorerUrl('solscan', transactionSignature);

console.log(solanaExplorerUrl); // "https://explorer.solana.com/tx/5iY4JfaVwEBBfVvhrBqqWc3F75xqM32wiEzdwSRzFnddqBTLiErPJr2XsqgfdTQkr92ygW4duSWCjLAomCnTdu3a?cluster=mainnet-beta"

console.log(solscanUrl); // "https://solscan.io/tx/5iY4JfaVwEBBfVvhrBqqWc3F75xqM32wiEzdwSRzFnddqBTLiErPJr2XsqgfdTQkr92ygW4duSWCjLAomCnTdu3a?cluster=mainnet-beta"
getAllExplorersUrl()

Definition

Returns all explorer URLs from Solana Explorer, Solscan, SolanaFM, and Solana Beach.

Example

import { getAllExplorersUrl } from 'solutils';

const transactionSignature = '55oJv5oCaez344JawHL5gnwqwrbrN4oD5ZN8rQFvyRSWzwXTTe178QG7KK9cR2wFkwecEca3V5vdbFexFG1ayECm';
const { urls } = getAllExplorersUrl(transactionSignature);

console.log(urls.solanaExplorerUrl); // "https://explorer.solana.com/tx/5iY4JfaVwEBBfVvhrBqqWc3F75xqM32wiEzdwSRzFnddqBTLiErPJr2XsqgfdTQkr92ygW4duSWCjLAomCnTdu3a?cluster=mainnet-beta"

console.log(urls.solscanUrl); // "https://solscan.io/tx/5iY4JfaVwEBBfVvhrBqqWc3F75xqM32wiEzdwSRzFnddqBTLiErPJr2XsqgfdTQkr92ygW4duSWCjLAomCnTdu3a?cluster=mainnet-beta"

Serialization

getEncodedBufferFromData()

Definition

Returns a serialized buffer from a data array, to afterwards use in your instructions.

⚠️ WARNING: Data sent to getEncodedBufferFromData should be in correct order that the program receives it.

Example

import { getClusterConnection, getEncodedBufferFromData, getSolanaExplorerUrl } from 'solutils';
import { Transaction, TransactionInstruction, sendAndConfirmTransaction } from '@solana/web3.js';

const connection = getClusterConnection('devnet');

const data = [
  { label: 'variant', type: 'u8', value: 2 },
  { label: 'playerId', type: 'u16', value: 1435 },
  { label: 'itemId', type: 'u128', value: 737498 },
] as DataItem[];

const { instructionBuffer } = getEncodedBufferFromData(data);

const transaction = new Transaction();
const instruction = new TransactionInstruction({
  data: instructionBuffer,
  programId: EXAMPLE_PROGRAM_ID,
  keys: [{ pubkey: EXAMPLE_PUBLIC_KEY, isSigner: true, isWritable: false }],
});

transaction.add(instruction);

sendAndConfirmTransaction(connection, transaction, [EXAMPLE_SIGNER]).then((transactionSignature) => {
  const { solanaExplorerUrl } = getSolanaExplorerUrl(transactionSignature, 'devnet');
  console.log(`Transaction submitted: ${solanaExplorerUrl}`);
});
getDecodedDataFromBufferAndSchema()

Definition

Returns a serialized buffer from a data array, to afterwards use in your instructions.

⚠️ WARNING: Data sent to getEncodedBufferFromData should be in correct order that the program receives it.

Example

import { getDecodedDataFromBufferAndSchema, getEncodedBufferFromData } from 'solutils';

// required initial schema
const schema = [
  { label: 'intialized', type: 'bool' },
  { label: 'playerId', type: 'u16' },
  { label: 'name', type: 'str' },
] as SchemaItem[];

// let's create a fake buffer, we probably get it from a PDA and will not be created by us
const bufferDataInput = [
  { label: 'initialized', type: 'bool', value: true },
  { label: 'playerId', type: 'u16', value: 1435 },
  { label: 'name', type: 'str', value: 'John Doe' },
] as DataItem[];
const { instructionBuffer } = getEncodedBufferFromData(bufferDataInput);

// get decodad data
const data = getDecodedDataFromBufferAndSchema(schema, instructionBuffer);
getEmptyBuffer()

Definition

Returns an empty buffer, needed when no data is mandatory to send to a Program.

Example

import { getEmptyBuffer } from 'solutils';

const connection = getClusterConnection('devnet');

const { instructionBuffer } = getEmptyBuffer(data);

const transaction = new Transaction();
const instruction = new TransactionInstruction({
  data: instructionBuffer,
  programId: EXAMPLE_PROGRAM_ID,
  keys: [{ pubkey: EXAMPLE_PUBLIC_KEY, isSigner: true, isWritable: false }],
});

transaction.add(instruction);

sendAndConfirmTransaction(connection, transaction, [EXAMPLE_SIGNER]).then((transactionSignature) => {
  const { solanaExplorerUrl } = getSolanaExplorerUrl(transactionSignature, 'devnet');
  console.log(`Transaction submitted: ${solanaExplorerUrl}`);
});

Transactions

getTransactionDetails()

Definition

Returns all details related to a transaction by sending its signature.

Example

import { getTransactionDetails } from 'solutils';

const transactionSignature = '55oJv5oCaez344JawHL5gnwqwrbrN4oD5ZN8rQFvyRSWzwXTTe178QG7KK9cR2wFkwecEca3V5vdbFexFG1ayECm';

const { connection } = getClusterConnection('mainnet-beta');
const { transactionDetails } = getTransactionDetails(transactionSignature, connection);

console.log(transactionDetails);
useTransactionDetails()

Definition

Same as previous method but in a hook form, accepting an autoTrigger which by defaults is true to automatically get transaction details. Also returns a getTransactionDetails method if you need to trigger the method through the UI.

Example

import { useTransactionDetails } from 'solutils';

function DemoComponent() {
  // constants
  const transactionSignature =
    '55oJv5oCaez344JawHL5gnwqwrbrN4oD5ZN8rQFvyRSWzwXTTe178QG7KK9cR2wFkwecEca3V5vdbFexFG1ayECm';

  // solutils hooks
  const { result, status, error } = useTransactionDetails(transactionSignature);

  return (
    <div>
      {status === 'iddle' ? <p>Haven't request any transaction details yet</p> : null}
      {status === 'loading' ? <p>Requesting your transaction details</p> : null}
      {status === 'success' ? <pre>{JSON.stringify(null, 2, result)}</pre> : null}
      {status === 'error' ? <p>Ups, something wrong happened</p> : null}
    </div>
  );
}

IDLs

getIdlFromAddress()

Definition

Returns IDL from an specific address. Optionally you can use a different cluster as a second parameter, which by default will be 'mainnet-beta'. You can use this method in a hook form useRequestIdlFromAddress().

Example

import { getIdlFromAddress } from 'solutils';

async function example() {
  const address = 'cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ';
  const { idl } = await getIdlFromAddress(address);

  console.log(idl); // { version: '4.4.0', name: 'candy_machine', ... }
}

example();
getInstructionFromIdl()

Definition

Returns a IDL instruction data (account and arguments) given his name.

Example

import { getIdlFromAddress, getInstructionFromIdl } from 'solutils';

async function example() {
  const address = 'cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ';

  const { idl } = await getIdlFromAddress(address);
  const { method } = await getInstructionFromIdl(idl, 'updateCandyMachine');

  console.log(method);

  /*
  {
    name: 'updateCandyMachine',
    accounts: [
      { name: 'candyMachine', isMut: true, isSigner: false },
      { name: 'authority', isMut: false, isSigner: true },
      { name: 'wallet', isMut: false, isSigner: false }
    ],
    args: [ { name: 'data', type: [ { name: 'data', type: { defined: 'CandyMachineData' } } ] } ]
  }
*/
}

example();
useRequestIdlFromAddress()

Definition

Returns a IDL from a particular address

Example

import { useRequestIdlFromAddress } from 'solutils';

function DemoComponent() {
  // solutils hooks
  const { getIdlFromAddress, idl, status } = useRequestIdlFromAddress();

  // constants
  const address = 'cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ';

  // handlers
  async function handleIdlRequest() {
    await getIdlFromAddress(address);
    console.log('Operation finalized');
  }

  return (
    <div>
      <button onClick={handleIdlRequest}>Request IDL</button>
      {status === 'iddle' ? <p>Haven't request any IDL yet</p> : null}
      {status === 'loading' ? <p>Requesting your IDL</p> : null}
      {status === 'success' ? <pre>{JSON.stringify(null, 2, idl)}</pre> : null}
      {status === 'error' ? <p>Ups, something wrong happened</p> : null}
    </div>
  );
}

PDAs

getPdaFromSeedAndProgramAddress()

Definition

Returns PDAs public key and address from a string seed and a program address.

Example

import { getPdaFromSeedAndProgramAddress } from 'solutils';

async function example() {
  const SEED = 'SOME_RANDOM_SEED';
  const PROGRAM_ADDRESS = 'CenYq6bDRB7p73EjsPEpiYN7uveyPUTdXkDkgUduboaN';

  const { pdaPublicKey, pdaAddress, bump } = await getPdaFromSeedAndProgramAddress(SEED, PROGRAM_ADDRESS);
}

example();
usePdaFromUserPublicKeyAndProgramAddress()

Definition

Use it to get PDA public key and address using public key from user connected wallet and a pogram address. Optionally getPdaFromUserPublicKeyAndProgramAddress accepts a second argument with a seeds string array.

Example

import { usePdaFromUserPublicKeyAndProgramAddress } from 'solutils';

function DemoComponent() {
  // solutils hooks
  const { getPdaFromUserPublicKeyAndProgramAddress, result, status, error } =
    usePdaFromUserPublicKeyAndProgramAddress();

  // constants
  const PROGRAM_ADDRESS = 'CenYq6bDRB7p73EjsPEpiYN7uveyPUTdXkDkgUduboaN';
  const EXTRA_SEEDS = ['part-a', 'part-b'];

  // handlers
  function handleRequestPDA() {
    getPdaFromUserPublicKeyAndProgramAddress(PROGRAM_ADDRESS, EXTRA_SEEDS);
  }

  return (
    <div>
      <button onClick={handleRequestPDA}>Request PDA</button>
      {status === 'iddle' ? <p>Haven't request any PDA yet</p> : null}
      {status === 'loading' ? <p>Requesting PDA...</p> : null}
      {status === 'success' ? <p>We successfully get PDA address: {result.pdaAddress}</p> : null}
      {status === 'error' ? <p>Ups, something wrong happened</p> : null}
    </div>
  );
}

Blockchain

getSolanaStatus()

Definition

Returns a isHealthy boolean to know blockchain current status

Example

import { getSolanaStatus } from 'solutils';

async function example() {
  const { isHealthy } = await getSolanaStatus();

  console.log(isHealthy); // true
}

example();
useSolanaStatus()

Definition

Same as previous method but by default re-fetchs Solana status every 30 seconds. Optionally refetching can be disabled using a false flag as a first parameter, and refetch interval could be also modified in ms as a second parameter.

Example

import { useSolanaStatus } from 'solutils';

function DemoComponent() {
  // solutils hooks
  const { result, status, error } = useSolanaStatus();

  return (
    <div>
      {result === true ? <p>All systems are operational</p> : null}
      {result === false ? <p>Blockchain is having some issues</p> : null}
      {status === 'loading' ? <p>Requesting blockchain status</p> : null}
      {status === 'error' ? <p>Ups, something wrong happened</p> : null}
    </div>
  );
}

Tokens

useUserBalance()

Definition

Returns user current balance in SOL.

Example

import { useUserBalance } from 'solutils';

function DemoComponent() {
  // solutils hooks
  const { getUserBalance, result, status } = useUserBalance();

  // handlers
  function handleUserBalanceRequest() {
    getUserBalance();
  }

  return (
    <div>
      <button onClick={handleUserBalanceRequest}>Request user balance</button>
      {status === 'iddle' ? <p>Haven't request any SOL balance yet</p> : null}
      {status === 'loading' ? <p>Requesting your SOL balance tokens</p> : null}
      {status === 'success' ? <p>We successfully get your balance: {userBalance} SOL</p> : null}
      {status === 'error' ? <p>Ups, something wrong happened</p> : null}
    </div>
  );
}
useRequestSolAirdrop()

Definition

Returns a function to request SOL airdrop for the connected wallet and a status variable to track transaction state.

Example

import { useRequestSolAirdrop } from 'solutils';

function DemoComponent() {
  // solutils hooks
  const { getSolAirdrop, result, status, error } = useRequestSolAirdrop();

  // constants
  const SOL = 2;

  // handlers
  function handleSolRequest() {
    getSolAirdrop(SOL);
  }

  return (
    <div>
      <button onClick={handleSolRequest}>Request Airdrop</button>
      {status === 'iddle' ? <p>Haven't request any SOL yet</p> : null}
      {status === 'loading' ? <p>Airdroping your SOL tokens</p> : null}
      {status === 'success' ? (
        <div>
          <p>Your {SOL} tokens have arrived, check your wallet!</p>
          <p>Transaction signature: {result.transactionSignature}</p>
          <a href={result.urls.solscanUrl} target='_blank'>
            Solscan
          </a>
          <a href={result.urls.solanaExplorerUrl} target='_blank'>
            Solana Explorer
          </a>
        </div>
      ) : null}
      {status === 'error' ? <p>Ups, something wrong happened</p> : null}
    </div>
  );
}
useTransferSolTokens()

Definition

Use it to transfer SOL tokens from connected wallet to a specific address.

Example

import { useTransferSolTokens } from 'solutils';

function DemoComponent() {
  // solutils hooks
  const { getTransferSolTokensReceipt, result, status, error } = useTransferSolTokens();

  // constants
  const SOL_TO_SEND = 0.5;
  const ADDRESS_TO_SEND = '5NSJUuR9Pn1yiFYGPWonqrVh72xxX8D2yADKrUf1USRc';

  // handlers
  function handleUserBalanceRequest() {
    getTransferSolTokensReceipt(SOL_TO_SEND, ADDRESS_TO_SEND);
  }

  return (
    <div>
      <button onClick={handleUserBalanceRequest}>Send {SOL_TO_SEND} SOL tokens</button>
      {status === 'iddle' ? <p>Haven't sent any SOL yet</p> : null}
      {status === 'loading' ? <p>Sending your SOL tokens</p> : null}
      {status === 'success' ? (
        <div>
          <p>We successfully sent: {SOL_TO_SEND} SOL</p>
          <p>Transaction signature: {result.transactionSignature}</p>
          <a href={result.urls.solscanUrl} target='_blank'>
            Solscan
          </a>
          <a href={result.urls.solanaExplorerUrl} target='_blank'>
            Solana Explorer
          </a>
        </div>
      ) : null}
      {status === 'error' ? <p>Ups, something wrong happened</p> : null}
    </div>
  );
}

Anchor

useAnchorProvider()

Definition

Returns an anchor provider receiving optionally a keypair parameter.

Example

import { useAnchorProvider } from 'solutils';

function DemoComponent() {
  // solutils hooks
  const { provider } = useAnchorProvider();
}

Contributors

lndgalante

Issues