🧪 MOCK MODE ACTIVE - No real tokens used
Documentation

Getting Started with SolPay

Learn how to integrate Lazorkit SDK to build passwordless, gasless payment experiences on Solana.

Installation

Install the required dependencies for your Next.js project:

Terminal
# Using pnpm (recommended)
pnpm add @lazorkit/wallet @solana/web3.js @solana/spl-token

# Using npm
npm install @lazorkit/wallet @solana/web3.js @solana/spl-token

# Using yarn
yarn add @lazorkit/wallet @solana/web3.js @solana/spl-token

Configuration

Create a .env.local file with your configuration:

.env.local
# Lazorkit Configuration
NEXT_PUBLIC_LAZORKIT_PORTAL_URL=https://portal.lazor.sh
NEXT_PUBLIC_LAZORKIT_PAYMASTER_URL=https://kora.devnet.lazorkit.com

# Solana Configuration  
NEXT_PUBLIC_SOLANA_NETWORK=devnet
NEXT_PUBLIC_RPC_URL=https://api.devnet.solana.com

# USDC Token (Devnet)
NEXT_PUBLIC_USDC_MINT=4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU

# Mock Mode (for testing without real tokens)
NEXT_PUBLIC_MOCK_MODE=true

Provider Setup

Wrap your application with the LazorkitProvider:

src/providers/WalletProvider.tsx
"use client";

import { LazorkitProvider } from "@lazorkit/wallet";

const config = {
  portalUrl: process.env.NEXT_PUBLIC_LAZORKIT_PORTAL_URL,
  paymasterUrl: process.env.NEXT_PUBLIC_LAZORKIT_PAYMASTER_URL,
};

export function WalletProvider({ children }) {
  return (
    <LazorkitProvider config={config}>
      {children}
    </LazorkitProvider>
  );
}

Authentication

Use the useWallet hook to handle authentication:

"use client";

import { useWallet } from "@lazorkit/wallet";

export function ConnectButton() {
  const { 
    connect,       // Create new passkey
    reconnect,     // Login with existing passkey
    disconnect,    // Logout
    isConnected,   // Connection status
    isConnecting,  // Loading state
    smartWalletPubkey // User's wallet address
  } = useWallet();

  if (isConnected) {
    return (
      <div>
        <p>Connected: {smartWalletPubkey?.toString()}</p>
        <button onClick={disconnect}>Disconnect</button>
      </div>
    );
  }

  return (
    <div>
      <button onClick={connect}>Create Account</button>
      <button onClick={reconnect}>Sign In</button>
    </div>
  );
}

Sending Transactions

Send gasless transactions using the signAndSendTransaction method:

Send SOL

import { useWallet } from "@lazorkit/wallet";
import { SystemProgram, PublicKey, LAMPORTS_PER_SOL } from "@solana/web3.js";

function SendSOL() {
  const { smartWalletPubkey, signAndSendTransaction } = useWallet();

  const sendSOL = async (recipient: string, amount: number) => {
    const instruction = SystemProgram.transfer({
      fromPubkey: smartWalletPubkey,
      toPubkey: new PublicKey(recipient),
      lamports: amount * LAMPORTS_PER_SOL,
    });

    // Transaction is automatically sponsored by Paymaster
    const signature = await signAndSendTransaction({
      instructions: [instruction],
    });

    console.log("Transaction:", signature);
  };

  return <button onClick={() => sendSOL("...", 0.1)}>Send 0.1 SOL</button>;
}

Send USDC

import { createTransferInstruction, getAssociatedTokenAddressSync } from "@solana/spl-token";

const sendUSDC = async (recipient: string, amount: number) => {
  const usdcMint = new PublicKey(USDC_MINT);
  
  // Get token accounts
  const fromAta = getAssociatedTokenAddressSync(usdcMint, smartWalletPubkey);
  const toAta = getAssociatedTokenAddressSync(usdcMint, new PublicKey(recipient));

  const instruction = createTransferInstruction(
    fromAta,
    toAta,
    smartWalletPubkey,
    amount * 1_000_000 // USDC has 6 decimals
  );

  const signature = await signAndSendTransaction({
    instructions: [instruction],
  });
};

Fetching Balance

import { Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";
import { getAccount, getAssociatedTokenAddressSync } from "@solana/spl-token";

const fetchBalances = async (walletPubkey: PublicKey) => {
  const connection = new Connection(RPC_URL);
  
  // SOL Balance
  const solBalance = await connection.getBalance(walletPubkey);
  const solAmount = solBalance / LAMPORTS_PER_SOL;
  
  // USDC Balance
  const usdcMint = new PublicKey(USDC_MINT);
  const ata = getAssociatedTokenAddressSync(usdcMint, walletPubkey);
  
  try {
    const account = await getAccount(connection, ata);
    const usdcAmount = Number(account.amount) / 1_000_000;
    return { sol: solAmount, usdc: usdcAmount };
  } catch {
    return { sol: solAmount, usdc: 0 };
  }
};

Resources

Ready to build?

Start building your own passwordless payment experience today.

Try the Demo