@solana-payment/sdk
v1.0.1
Published
TypeScript SDK for Solana Payment Contract - Build unsigned transactions for frontend
Maintainers
Readme
@solana-payment/sdk
TypeScript SDK for Solana Payment Contract - Build unsigned transactions for frontend applications.
Features
- 🔐 Wallet-agnostic: Build unsigned transactions, let frontend handle signing
- 🎯 Type-safe: Full TypeScript support with comprehensive types
- 🚀 Simple API: Clean, intuitive methods for all contract operations
- 📦 Zero wallet dependencies: No wallet adapter required
- ⚡ Anchor-based: Built on Anchor framework for reliability
Installation
pnpm add @solana-payment/sdkOr using npm/yarn:
npm install @solana-payment/sdk
yarn add @solana-payment/sdkBrowser/Frontend Setup
If you're using this SDK in a browser environment (React, Next.js, Vue, etc.), you need to configure Buffer polyfill. This SDK includes buffer as a dependency, but your bundler needs to be configured properly.
Quick setup for Vite:
// vite.config.ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [react()],
resolve: {
alias: {
buffer: 'buffer',
},
},
define: {
'global': 'globalThis',
},
});
// main.tsx
import { Buffer } from 'buffer';
window.Buffer = Buffer;For Next.js, Create React App, Webpack, and other frameworks: See detailed setup guide in docs/BROWSER_SETUP.md
Quick Start
import { VaultSDK, PROGRAM_ID } from '@solana-payment/sdk';
import { Connection, PublicKey } from '@solana/web3.js';
// Initialize SDK
const connection = new Connection('https://api.devnet.solana.com');
const sdk = new VaultSDK({
connection,
programId: PROGRAM_ID, // Optional, uses default if not provided
});
// Build a deposit transaction
const depositTx = await sdk.buildDepositTransaction({
amount: 1000000, // Amount in raw token units
user: userPublicKey,
mint: tokenMintPublicKey,
});
// Frontend signs and sends (using wallet adapter or other method)
await wallet.signTransaction(depositTx);
await connection.sendRawTransaction(depositTx.serialize());API Documentation
Constructor
new VaultSDK(config: VaultSDKConfig)Parameters:
config.connection: Solana Connection instanceconfig.programId: Program ID (optional, defaults to deployed program)
Query Methods
getConfig()
Fetch vault configuration from on-chain.
const config = await sdk.getConfig();
console.log('Admin:', config.admin.toString());
console.log('Mint:', config.mint.toString());Returns: Promise<VaultConfig>
getVaultBalance(mint)
Get current vault balance for a specific token mint.
const balance = await sdk.getVaultBalance(mintPublicKey);
console.log('Raw amount:', balance.amount);
console.log('Formatted:', balance.formatted);
console.log('Decimals:', balance.decimals);Parameters:
mint: Token mint PublicKey
Returns: Promise<VaultBalanceInfo>
isInitialized()
Check if vault has been initialized.
const initialized = await sdk.isInitialized();
if (!initialized) {
console.log('Vault needs to be initialized');
}Returns: Promise<boolean>
Transaction Builders
All transaction builder methods return unsigned Transaction objects that need to be signed by the frontend before submission.
buildInitializeTransaction(params)
Build transaction to initialize the vault (one-time setup).
const tx = await sdk.buildInitializeTransaction({
admin: adminPublicKey,
mint: tokenMintPublicKey,
payer: payerPublicKey,
});
// Sign and send
await wallet.signTransaction(tx);
await connection.sendRawTransaction(tx.serialize());Parameters:
admin: PublicKey of the adminmint: PublicKey of the SPL token mintpayer: PublicKey paying for transaction fees
Returns: Promise<Transaction>
buildDepositTransaction(params)
Build transaction to deposit tokens into the vault.
const tx = await sdk.buildDepositTransaction({
amount: 1000000, // Raw token amount (e.g., 1 USDC = 1000000 with 6 decimals)
user: userPublicKey,
mint: tokenMintPublicKey,
});
// Sign and send
await wallet.signTransaction(tx);
await connection.sendRawTransaction(tx.serialize());Parameters:
amount: Amount to deposit (number or BN)user: PublicKey of the user depositingmint: PublicKey of the token mint
Returns: Promise<Transaction>
buildWithdrawTransaction(params)
Build transaction to withdraw tokens from the vault (admin only).
const tx = await sdk.buildWithdrawTransaction({
amount: 500000,
admin: adminPublicKey,
recipient: recipientPublicKey,
mint: tokenMintPublicKey,
});
// Admin signs and sends
await adminWallet.signTransaction(tx);
await connection.sendRawTransaction(tx.serialize());Parameters:
amount: Amount to withdraw (number or BN)admin: PublicKey of the admin (must match vault config)recipient: PublicKey receiving the tokensmint: PublicKey of the token mint
Returns: Promise<Transaction>
buildUpdateAdminTransaction(params)
Build transaction to update vault admin (current admin only).
const tx = await sdk.buildUpdateAdminTransaction({
currentAdmin: currentAdminPublicKey,
newAdmin: newAdminPublicKey,
});
// Current admin signs and sends
await adminWallet.signTransaction(tx);
await connection.sendRawTransaction(tx.serialize());Parameters:
currentAdmin: PublicKey of current admin (must match vault config)newAdmin: PublicKey of new admin
Returns: Promise<Transaction>
Factory Pattern (Singleton)
For applications that need a single SDK instance:
import { initVaultSDK, getVaultSDK } from '@solana-payment/sdk';
// Initialize once
initVaultSDK({ connection, programId });
// Use anywhere in your app
const sdk = getVaultSDK();
const config = await sdk.getConfig();Advanced Usage
Working with Token Amounts
The SDK provides utilities for handling token amounts with decimals:
import { formatTokenAmount, validateAmount } from '@solana-payment/sdk';
import { BN } from '@coral-xyz/anchor';
// Format raw amount with decimals
const formatted = formatTokenAmount(new BN(1000000), 6);
console.log(formatted); // "1"
// Validate and convert to BN
const amount = validateAmount(1000000);PDA Derivation
Manually derive PDAs if needed:
import {
deriveConfigPDA,
deriveVaultPDA,
findVaultTokenAccount,
findUserTokenAccount,
} from '@solana-payment/sdk';
const { publicKey: configPDA, bump } = await deriveConfigPDA();
const { publicKey: vaultPDA } = await deriveVaultPDA(configPDA);
const vaultATA = await findVaultTokenAccount(vaultPDA, mint);
const userATA = await findUserTokenAccount(userPubkey, mint);Error Handling
try {
const tx = await sdk.buildDepositTransaction({
amount: 0, // Invalid: will throw
user: userPublicKey,
mint: mintPublicKey,
});
} catch (error) {
console.error('Failed to build transaction:', error.message);
// Error: Amount must be greater than 0
}Common errors:
"Amount must be greater than 0"- Invalid amount parameter"Missing required parameters"- Required parameters not provided"Config account not found"- Vault not initialized"New admin must be different from current admin"- Same admin provided
Integration Examples
React with Wallet Adapter
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
import { VaultSDK } from '@solana-payment/sdk';
function DepositButton() {
const { connection } = useConnection();
const { publicKey, signTransaction } = useWallet();
const handleDeposit = async () => {
if (!publicKey || !signTransaction) return;
const sdk = new VaultSDK({ connection });
const tx = await sdk.buildDepositTransaction({
amount: 1000000,
user: publicKey,
mint: USDC_MINT,
});
const signed = await signTransaction(tx);
const signature = await connection.sendRawTransaction(signed.serialize());
await connection.confirmTransaction(signature);
};
return <button onClick={handleDeposit}>Deposit</button>;
}Next.js API Route
// pages/api/build-transaction.ts
import { Connection, PublicKey } from '@solana/web3.js';
import { VaultSDK } from '@solana-payment/sdk';
export default async function handler(req, res) {
const { amount, user, mint } = req.body;
const connection = new Connection(process.env.RPC_URL);
const sdk = new VaultSDK({ connection });
const tx = await sdk.buildDepositTransaction({
amount: Number(amount),
user: new PublicKey(user),
mint: new PublicKey(mint),
});
// Serialize and send to frontend
const serialized = tx.serialize({ requireAllSignatures: false });
res.json({ transaction: serialized.toString('base64') });
}Constants
import {
PROGRAM_ID,
TOKEN_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID,
RPC_ENDPOINTS,
} from '@solana-payment/sdk';
console.log('Program ID:', PROGRAM_ID.toString());
console.log('Devnet RPC:', RPC_ENDPOINTS.devnet);TypeScript Types
The SDK exports all TypeScript types for use in your application:
import type {
VaultSDKConfig,
VaultConfig,
InitializeParams,
DepositParams,
WithdrawParams,
UpdateAdminParams,
VaultBalanceInfo,
} from '@solana-payment/sdk';Development
# Install dependencies
pnpm install
# Build SDK
pnpm build
# Watch mode
pnpm watchLicense
MIT
Support
For issues and questions, please open an issue on GitHub.
