ShainShain/docs
Shain/Docs/ShainClient
SDK

ShainClient

Thin wrapper around @solana/web3.js that holds a Connection, a wallet, and a program id. Everything else is composable helpers.

Construct

new ShainClienttypescript
import { Connection, Keypair, PublicKey } from "@solana/web3.js";
import { ShainClient } from "@shain/sdk";

const client = new ShainClient({
  connection: new Connection("https://api.devnet.solana.com", "confirmed"),
  programId: new PublicKey("2T1Qs7f2hiy1sUQBWC7226xhXvCees97UfeqReRrnE66"),
  wallet: Keypair.generate(),     // or a wallet-adapter instance
  commitment: "confirmed",         // optional; default "confirmed"
});

PDA helpers

MethodReturnsNotes
client.pdas(holder?)PdaDerivationOutputConfig + treasury PDAs; session PDA if holder passed
client.ata(owner, mint)PublicKeyAssociated Token Address
client.walletPublicKey()PublicKeyResolves Keypair | WalletLike

Fetchers

MethodReturnsNotes
fetchConfig()Promise<ShainConfig | null>Singleton config PDA
fetchSession(holder?)Promise<ShainSession | null>Defaults to wallet.publicKey
snapshotSession(holder?)Promise<SessionSnapshot | null>UI-ready projection
predictExpiry()Promise<number | null>Reads config, returns now + duration

Instruction builders

Every on-chain call has a build*Ix variant that returns a raw TransactionInstruction. Use these when you want to bundle Shain with other ixs (a DEX swap, an ATA create, etc.) in a single transaction.

MethodSignatureWhen
buildInitializeIx(args) => TransactionInstructionDeployment only
buildStartSessionIx({shainMint, userTokenAccount}) => TransactionInstructionOpen a session
buildGatedActionIx({tag?}) => TransactionInstructionGate any downstream call
buildCloseSessionIx({user}) => TransactionInstructionPost-expiry cleanup

High-level helpers

Each builder has a one-shot counterpart that builds, signs and sends in one call:

high-leveltypescript
const result = await client.startSession({
  shainMint,
  userTokenAccount: userAta,
});
// { signature, sessionPda, startedAt, expiresAt }

const hook = await client.gatedAction({ tag: 1n });
// { signature, tag, actionsCount }

const closed = await client.closeSession({ user: wallet.publicKey });
// { signature, refundedLamports }

With wallet adapter

wallet-adapter.tsxtypescript
import { useConnection, useWallet } from "@solana/wallet-adapter-react";
import { ShainClient } from "@shain/sdk";
import { Transaction } from "@solana/web3.js";

function useShain() {
  const { connection } = useConnection();
  const { publicKey, signTransaction } = useWallet();

  return useMemo(() => {
    if (!publicKey) return null;
    return new ShainClient({
      connection,
      programId: DEFAULT_PROGRAM_ID,
      wallet: { publicKey, signTransaction },
    });
  }, [connection, publicKey, signTransaction]);
}

async function openSession(client: ShainClient, mint: PublicKey, ata: PublicKey) {
  const ix = client.buildStartSessionIx({
    shainMint: mint,
    userTokenAccount: ata,
  });
  const tx = new Transaction().add(ix);
  tx.feePayer = client.walletPublicKey();
  tx.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
  const signed = await signTransaction(tx);
  return connection.sendRawTransaction(signed.serialize());
}