npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@zebec-network/zebec-card-v2-sdk

v2.6.0

Published

This is an SDK for interacting with ZEBEC Card Program in solana

Readme

Zebec Card V2 SDK

A TypeScript SDK for interacting with the Zebec Card Program on Solana blockchain. This SDK provides a comprehensive interface for creating and managing virtual cards with crypto-to-fiat conversion capabilities.

Features

  • Card Creation & Management: Create Silver and Carbon cards with customizable configurations
  • Token Swapping: Integrated Jupiter aggregator support for seamless token swaps
  • Partner Integration: Support for partner-specific card configurations and custom fees
  • Fee Management: Flexible fee structures with tiered pricing and custom token fees
  • Daily Limits: Built-in daily purchase limits and tracking
  • Type Safety: Full TypeScript support with comprehensive type definitions

Installation

npm install @zebec-network/zebec-card-v2-sdk

Prerequisites

  • Node.js >= 14
  • @coral-xyz/anchor >= 0.31.1
  • @solana/web3.js >= 1.98.2

Quick Start

Initialize the Service

import {
  ZebecCardV2Service,
  createAnchorProvider,
} from "@zebec-network/zebec-card-v2-sdk";
import { Connection, Keypair } from "@solana/web3.js";

// Create connection
const connection = new Connection("https://api.mainnet-beta.solana.com");

// Create provider using the SDK helper (wallet must implement AnchorWallet interface)
const provider = createAnchorProvider(connection, wallet);

// Initialize service
const cardService = ZebecCardV2Service.create(provider, "mainnet-beta");

Email Hash

All card creation methods require a 32-byte Buffer email hash. Use hashSHA256ToBuffer from @zebec-network/core-utils:

import { hashSHA256ToBuffer } from "@zebec-network/core-utils";

const emailHash = await hashSHA256ToBuffer("[email protected]");

Get Next Card Index

Before creating a card, fetch the next available card counter for the user:

const nextCardCounter = await cardService.getNextCardIndex();

Create a Silver Card

const payload = await cardService.createSilverCard({
  userAddress: userPublicKey,
  nextCardCounter,
  amount: "100", // USDC amount
  inputMintAddress: usdcMintAddress,
  outputMintAddress: usdcMintAddress,
  emailHash,
  currency: "USD",
});

const signature = await payload.execute({ commitment: "confirmed" });

Swap and Create Card

// Fetch a quote from Jupiter (GET request with query parameters)
const queryParams = new URLSearchParams({
  inputMint: "So11111111111111111111111111111111111111112", // SOL
  outputMint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC
  amount: "90000000", // 0.09 SOL in lamports
  slippageBps: "10", // 0.1% slippage
  swapMode: "ExactIn",
});

const quoteInfo = await fetch(
  `https://lite-api.jup.ag/swap/v1/quote?${queryParams}`
).then((res) => res.json());

// Create card with swap
const payload = await cardService.swapAndCreateSilverCard({
  quoteInfo,
  userAddress: userPublicKey,
  nextCardCounter,
  emailHash,
  currency: "USD",
  wrapAndUnwrapWsol: true,
});

await payload.execute({ commitment: "confirmed" });

Card Types

Silver Card

One-time use virtual card created with a specific amount.

await cardService.createSilverCard({
  userAddress: Address,
  nextCardCounter: bigint,
  amount: Numeric,            // USDC amount as string or number
  inputMintAddress: Address,  // token being spent
  outputMintAddress: Address, // must be USDC
  emailHash: Buffer,          // 32-byte SHA-256 hash
  currency: string,           // e.g. "USD"
  feePayer?: Address,         // optional, defaults to userAddress
});

Carbon Card

Reloadable virtual card that can be topped up multiple times.

await cardService.loadCarbonCard({
  userAddress: Address,
  nextCardCounter: bigint,
  amount: Numeric,
  inputMintAddress: Address,
  outputMintAddress: Address,
  emailHash: Buffer,
  currency: string,
  reloadCardId: string,       // identifier for the card being reloaded
  feePayer?: Address,
});

Configuration Management

Initialize Card Config (Admin)

await cardService.initCardConfig({
  zicOwnerAddress?: Address,     // optional, defaults to provider.publicKey
  cardVaultAddress: Address,
  revenueVaultAddress: Address,
  commissionVaultAddress: Address,
  usdcAddress: Address,
  revenueFeePercent: Numeric,    // e.g. "1.0"
  nativeFeePercent: Numeric,     // fee for native SOL swaps
  nonNativeFeePercent: Numeric,  // fee for non-native token swaps
  carbonFeePercent: Numeric,     // fee for Carbon card loads
  minCardAmount: Numeric,        // minimum USDC amount per card
  maxCardAmount: Numeric,        // maximum USDC amount per card
  dailyCardPurchaseLimit: Numeric,
  feeTiers: FeeTier[],
});

Update Card Config

await cardService.setCardConfig({
  zicOwnerAddress?: Address,
  newZicOwnerAddress: Address,
  cardVaultAddress: Address,
  revenueVaultAddress: Address,
  commissionVaultAddress: Address,
  revenueFeePercent: Numeric,
  nativeFeePercent: Numeric,
  nonNativeFeePercent: Numeric,
  carbonFeePercent: Numeric,
  minCardAmount: Numeric,
  maxCardAmount: Numeric,
  dailyCardPurchaseLimit: Numeric,
  feeTiers: FeeTier[],
});

Set Custom Token Fees

await cardService.setCustomFees({
  tokenFeeList: [
    { tokenAddress: solMintAddress, fee: "1.5" },
    { tokenAddress: usdtMintAddress, fee: "2.0" },
  ],
});

Delete Custom Token Fees

await cardService.deleteCustomFees({
  tokenAddressList: [solMintAddress, usdtMintAddress],
});

Partner Integration

The SDK supports partner-specific configurations with separate fee structures.

Initialize Partner Config (Admin)

import { ZebecPartnerCardService } from "@zebec-network/zebec-card-v2-sdk";

// partnershipName is bound at construction time
const partnerService = ZebecPartnerCardService.create(
  "MyPartner",
  provider,
  "mainnet-beta",
);

await partnerService.initPartnerCardConfig({
  zicOwnerAddress?: Address,  // optional, defaults to provider.publicKey
  cardVaultAddress: Address,
  revenueVaultAddress: Address,
  usdcAddress: Address,
  carbonFeePercent: Numeric,
  minCardAmount: Numeric,
  maxCardAmount: Numeric,
  dailyCardPurchaseLimit: Numeric,
  feeTiers: FeeTier[],
});

Update Partner Config

await partnerService.setPartnerCardConfig({
  zicOwnerAddress?: Address,
  newZicOwnerAddress: Address,
  cardVaultAddress: Address,
  revenueVaultAddress: Address,
  carbonFeePercent: Numeric,
  minCardAmount: Numeric,
  maxCardAmount: Numeric,
  dailyCardPurchaseLimit: Numeric,
  feeTiers: FeeTier[],
});

Create Partner Silver Card

await partnerService.createPartnerSilverCard({
  userAddress: Address,
  nextCardCounter: bigint,
  amount: Numeric,
  inputMintAddress: Address,
  outputMintAddress: Address,
  emailHash: Buffer,
  currency: string,
  feePayer?: Address,
});

Load Partner Carbon Card

await partnerService.loadPartnerCarbonCard({
  userAddress: Address,
  nextCardCounter: bigint,
  amount: Numeric,
  inputMintAddress: Address,
  outputMintAddress: Address,
  emailHash: Buffer,
  currency: string,
  reloadCardId: string,
  feePayer?: Address,
});

Swap and Create Partner Cards

// Swap and create
await partnerService.swapAndCreatePartnerSilverCard({
  quoteInfo,
  userAddress: Address,
  nextCardCounter: bigint,
  emailHash: Buffer,
  currency: string,
  wrapAndUnwrapWsol?: boolean,
  feePayer?: Address,
});

// Swap and load
await partnerService.swapAndLoadPartnerCarbonCard({
  quoteInfo,
  userAddress: Address,
  nextCardCounter: bigint,
  emailHash: Buffer,
  currency: string,
  reloadCardId: string,
  wrapAndUnwrapWsol?: boolean,
  feePayer?: Address,
});

Partner Custom Fees

// Set
await partnerService.setPartnerCustomFees({
  tokenFeeList: [{ tokenAddress: solMintAddress, fee: "1.5" }],
});

// Delete
await partnerService.deletePartnerCustomFees({
  tokenAddressList: [solMintAddress],
});

Data Retrieval

Standard Service

// Card configuration
const config = await cardService.getCardConfigInfo();
console.log({
  index: config.index,
  minAmount: config.providerConfig.minCardAmount,
  maxAmount: config.providerConfig.maxCardAmount,
  totalCardSold: config.totalCardSold,
  dailyCardPurchaseLimit: config.dailyCardPurchaseLimit,
  feeTiers: config.providerConfig.feeTiers,
});

// Purchase info
const purchaseInfo = await cardService.getCardPurchaseInfo(cardPurchasePda);
console.log({
  amount: purchaseInfo.amount,
  buyer: purchaseInfo.buyerAddress,
  timestamp: purchaseInfo.purchaseAt,
});

// User daily purchase record
const userRecord = await cardService.getUserPurchaseRecord(userPurchaseRecordPda);
console.log({
  dailyTotal: userRecord.totalCardBoughtPerDay,
  lastPurchase: new Date(userRecord.lastCardBoughtTimestamp * 1000),
});

// Custom token fees
const fees = await cardService.getCustomTokenFees();

// Next card index
const nextCardCounter = await cardService.getNextCardIndex();

Partner Service

// Partner card configuration (uses this.partnershipName internally)
const partnerConfig = await partnerService.getPartnerCardConfigInfo();

// Partner custom fees (uses this.partnershipName internally)
const partnerFees = await partnerService.getPartnerCustomTokenFees();

// Partner user purchase record
const partnerUserRecord = await partnerService.getPartnerUserPurchaseRecord(pda);

// Purchase info (same as standard)
const purchaseInfo = await partnerService.getCardPurchaseInfo(pda);

// Next card index for partner (partnershipName must be passed explicitly)
const nextCardCounter = await partnerService.getNextCardIndex("MyPartner");

PDA Derivation

import {
  deriveCardConfigPda,
  deriveCardPurchasePda,
  deriveUserPurchaseRecordPda,
  deriveTokenFeeMapPda,
  derivePartnerCardConfigPda,
  derivePartnerCardPurchasePda,
  derivePartnerUserPurchaseRecordPda,
  derivePartnerTokenFeeMapPda,
} from "@zebec-network/zebec-card-v2-sdk";

const programId = cardService.program.programId;

// Standard PDAs
const [cardConfigPda] = deriveCardConfigPda(programId);
const [tokenFeeMapPda] = deriveTokenFeeMapPda(programId);
const [purchasePda] = deriveCardPurchasePda(userAddress, nextCardCounter, programId);
const [userRecordPda] = deriveUserPurchaseRecordPda(userAddress, programId);

// Partner PDAs
const [partnerConfigPda] = derivePartnerCardConfigPda(programId, "PartnerName");
const [partnerTokenFeeMapPda] = derivePartnerTokenFeeMapPda(partnerConfigPda, programId);
const [partnerPurchasePda] = derivePartnerCardPurchasePda(userAddress, partnerConfigPda, nextCardCounter, programId);
const [partnerUserRecordPda] = derivePartnerUserPurchaseRecordPda(userAddress, partnerConfigPda, programId);

Error Handling

import {
  NotEnoughBalanceError,
  AmountOutOfRangeError,
  DailyCardLimitReachedError,
  InvalidUsdcAddressError,
  QuoteResponseError,
  AssociatedTokenAccountDoesNotExistsError,
} from "@zebec-network/zebec-card-v2-sdk";

try {
  await cardService.createSilverCard(params);
} catch (error) {
  if (error instanceof NotEnoughBalanceError) {
    console.error("Insufficient balance");
  } else if (error instanceof AmountOutOfRangeError) {
    console.error(`Amount must be between ${error.minRange} and ${error.maxRange}`);
  } else if (error instanceof DailyCardLimitReachedError) {
    console.error(`Daily limit of ${error.dailyCardLimit} reached`);
  } else if (error instanceof InvalidUsdcAddressError) {
    console.error(`Invalid USDC mint: ${error.mintAddress}`);
  }
}

Fee Tiers

Fee tiers allow for progressive pricing based on card amounts:

const feeTiers: FeeTier[] = [
  { minAmount: "0",    maxAmount: "100",   feePercent: "3.0" },
  { minAmount: "100",  maxAmount: "500",   feePercent: "2.5" },
  { minAmount: "500",  maxAmount: "1000",  feePercent: "2.0" },
  { minAmount: "1000", maxAmount: "10000", feePercent: "1.5" },
];

Readonly Provider

For read-only operations without wallet signing:

import { createReadonlyProvider } from "@zebec-network/zebec-card-v2-sdk";

const readonlyProvider = createReadonlyProvider(
  connection,
  userPublicKey, // optional
);

const cardService = ZebecCardV2Service.create(readonlyProvider, "mainnet-beta");
const config = await cardService.getCardConfigInfo();

Network Support

The SDK supports Solana mainnet-beta and devnet. The network argument must match the cluster of the connection:

// Mainnet
const mainnetService = ZebecCardV2Service.create(provider, "mainnet-beta");

// Devnet
const devnetService = ZebecCardV2Service.create(devnetProvider, "devnet");

Transaction Building

All transaction-creating methods return a TransactionPayload object:

const payload = await cardService.createSilverCard(params);

// Execute and get signature
const signature = await payload.execute({ commitment: "confirmed" });

// Simulate without submitting
const result = await payload.simulate({ commitment: "confirmed" });
console.log(result.value.logs);

// Get raw versioned transaction for manual handling
const transaction = await payload.getTransaction();

Best Practices

  1. Amount Precision: Always provide amounts as strings to avoid floating-point precision issues
  2. Email Hash: Use hashSHA256ToBuffer from @zebec-network/core-utils to produce the required 32-byte Buffer
  3. Card Counter: Always call getNextCardIndex() immediately before creating a card to avoid counter collisions
  4. Error Handling: Implement comprehensive error handling for all transaction operations
  5. Network Validation: Ensure your connection and service network match — the SDK will throw on mismatch
  6. Daily Limits: Check getUserPurchaseRecord before creating cards to prevent DailyCardLimitReachedError

API Reference

ZebecCardV2Service

Main service class for standard card operations.

Factory:

  • create(provider, network) — Create a service instance

Card Configuration (Admin):

  • initCardConfig(params)Promise<TransactionPayload>
  • setCardConfig(params)Promise<TransactionPayload>

Card Creation:

  • createSilverCard(params)Promise<TransactionPayload>
  • loadCarbonCard(params)Promise<TransactionPayload>
  • swapAndCreateSilverCard(params)Promise<TransactionPayload>
  • swapAndLoadCarbonCard(params)Promise<TransactionPayload>

Fee Management (Admin):

  • setCustomFees(params)Promise<TransactionPayload>
  • deleteCustomFees(params)Promise<TransactionPayload>

Data Retrieval:

  • getNextCardIndex()Promise<bigint>
  • getCardConfigInfo()Promise<CardConfigInfo>
  • getCardPurchaseInfo(pda)Promise<CardPurchaseInfo>
  • getUserPurchaseRecord(pda)Promise<UserPurchaseRecordInfo>
  • getCustomTokenFees()Promise<TokenFeeRecord[]>

ZebecPartnerCardService

Service class for partner-specific card operations.

Factory:

  • create(partnershipName, provider, network) — Create a service instance; partnershipName is bound to all subsequent calls

Partner Configuration (Admin):

  • initPartnerCardConfig(params)Promise<TransactionPayload>
  • setPartnerCardConfig(params)Promise<TransactionPayload>

Card Creation:

  • createPartnerSilverCard(params)Promise<TransactionPayload>
  • loadPartnerCarbonCard(params)Promise<TransactionPayload>
  • swapAndCreatePartnerSilverCard(params)Promise<TransactionPayload>
  • swapAndLoadPartnerCarbonCard(params)Promise<TransactionPayload>

Fee Management (Admin):

  • setPartnerCustomFees(params)Promise<TransactionPayload>
  • deletePartnerCustomFees(params)Promise<TransactionPayload>

Data Retrieval:

  • getNextCardIndex(partnershipName)Promise<bigint> — requires explicit partnershipName
  • getPartnerCardConfigInfo()Promise<PartnerCardConfigInfo> — uses this.partnershipName
  • getCardPurchaseInfo(pda)Promise<CardPurchaseInfo>
  • getPartnerUserPurchaseRecord(pda)Promise<UserPurchaseRecordInfo>
  • getPartnerCustomTokenFees()Promise<TokenFeeRecord[]> — uses this.partnershipName

Provider Utilities

import {
  createAnchorProvider,
  createReadonlyProvider,
} from "@zebec-network/zebec-card-v2-sdk";

// For signing transactions
createAnchorProvider(connection, wallet, options?) → AnchorProvider

// For read-only queries
createReadonlyProvider(connection, walletAddress?) → ReadonlyProvider

Key Types

type FeeTier = {
  minAmount: Numeric;
  maxAmount: Numeric;
  feePercent: Numeric;
};

type TokenFeeRecord = {
  tokenAddress: Address;
  fee: Numeric;
};

type CardConfigInfo = {
  address: Address;
  index: bigint;
  zicOwner: Address;
  nativeFeePercent: Numeric;
  nonNativeFeePercent: Numeric;
  revenueFeePercent: Numeric;
  carbonFeePercent: Numeric;
  usdcMint: Address;
  revenueVault: Address;
  commissionVault: Address;
  cardVault: Address;
  totalCardSold: Numeric;
  dailyCardPurchaseLimit: Numeric;
  providerConfig: ProviderConfig;
};

type PartnerCardConfigInfo = {
  address: Address;
  partnerName: string;
  index: bigint;
  zicOwner: Address;
  carbonFeePercent: Numeric;
  usdcMint: Address;
  revenueVault: Address;
  cardVault: Address;
  totalCardSold: Numeric;
  dailyCardPurchaseLimit: Numeric;
  providerConfig: ProviderConfig;
};

type ProviderConfig = {
  minCardAmount: Numeric;
  maxCardAmount: Numeric;
  feeTiers: FeeTier[];
};

type CardPurchaseInfo = {
  address: Address;
  index: bigint;
  buyerAddress: Address;
  amount: Numeric;
  purchaseAt: number; // Unix timestamp
};

type UserPurchaseRecordInfo = {
  address: Address;
  owner: Address;
  lastCardBoughtTimestamp: number; // Unix timestamp
  totalCardBoughtPerDay: Numeric;
};

License

MIT

Support

For issues and questions:

Contributing

Contributions are welcome! Please read our contributing guidelines before submitting pull requests.