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

karma-presale-sdk

v1.0.0

Published

TypeScript SDK for participating in Karma Reputation Presales

Downloads

86

Readme

Karma Presale SDK

TypeScript SDK for participating in Karma Reputation Presales.

Installation

npm install @karma/presale-sdk viem

Quick Start

import { createPublicClient, createWalletClient, http } from "viem";
import { mainnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { KarmaPresaleSDK, PresaleStatus } from "@karma/presale-sdk";

// Create clients
const publicClient = createPublicClient({
  chain: mainnet,
  transport: http(),
});

const account = privateKeyToAccount("0x...");
const walletClient = createWalletClient({
  account,
  chain: mainnet,
  transport: http(),
});

// Initialize SDK
const sdk = new KarmaPresaleSDK(
  {
    presaleContractAddress: "0x...",
    usdcAddress: "0x...",
    chainId: mainnet.id,
  },
  publicClient,
  walletClient
);

// Participate in presale
const presaleId = 1n;
const amount = sdk.parseUsdc("1000"); // 1000 USDC

// Approve and contribute
await (await sdk.approveUsdc(amount)).wait();
await (await sdk.contribute({ presaleId, amount })).wait();

Features

  • Type-safe: Full TypeScript support with comprehensive types
  • Viem Integration: Built on top of viem for modern Ethereum interactions
  • Error Handling: Custom error classes for better error handling
  • Utility Functions: Helpers for formatting, parsing, and status checks

API Reference

Initialization

const sdk = new KarmaPresaleSDK(config, publicClient, walletClient?);

Config

| Property | Type | Description | |----------|------|-------------| | presaleContractAddress | Address | Presale contract address | | usdcAddress | Address | USDC token address | | chainId | number | Chain ID |

Read Functions

Get Presale Info

// Get presale details
const presale = await sdk.getPresale(presaleId);

// Get full presale info including supply tracking
const presaleInfo = await sdk.getPresaleInfo(presaleId);

// Get user-specific info
const userInfo = await sdk.getUserPresaleInfo(presaleId, userAddress);

Get User Data

// Get user's contribution
const contribution = await sdk.getContribution(presaleId, userAddress);

// Get user's token allocation
const allocation = await sdk.getTokenAllocation(presaleId, userAddress);

// Get user's refund amount
const refund = await sdk.getRefundAmount(presaleId, userAddress);

// Check claim status
const tokensClaimed = await sdk.hasClaimedTokens(presaleId, userAddress);
const refundClaimed = await sdk.hasClaimedRefund(presaleId, userAddress);

USDC Balance & Allowance

const balance = await sdk.getUsdcBalance(userAddress);
const allowance = await sdk.getUsdcAllowance(userAddress);

Write Functions

Approve USDC

// Approve specific amount
const result = await sdk.approveUsdc(amount);
await result.wait();

// Approve max (unlimited)
const result = await sdk.approveMaxUsdc();
await result.wait();

Contribute

// Contribute (requires prior approval)
const result = await sdk.contribute({ presaleId, amount });
await result.wait();

// Contribute with automatic approval
const result = await sdk.contributeWithApproval({ presaleId, amount });
await result.wait();

Withdraw

const result = await sdk.withdrawContribution({ presaleId, amount });
await result.wait();

Claim Tokens

const result = await sdk.claimTokens({ presaleId });
await result.wait();

Claim Refund

const result = await sdk.claimRefund({ presaleId });
await result.wait();

Utility Functions

Formatting & Parsing

// USDC (6 decimals)
sdk.formatUsdc(1000000n); // "1"
sdk.parseUsdc("1000"); // 1000000000n

// Tokens (18 decimals)
sdk.formatTokens(1000000000000000000n); // "1"
sdk.parseTokens("1000"); // 1000000000000000000000n

Status Helpers

sdk.isPresaleActive(presale); // boolean
sdk.isPresaleClaimable(presale); // boolean
sdk.isPresaleFailed(presale); // boolean

sdk.getPresaleStatusString(PresaleStatus.Active); // "Active"

sdk.getTimeRemaining(presale); // seconds until end
sdk.getProgressPercentage(presale); // 0-100

Presale Status Enum

enum PresaleStatus {
  NotCreated = 0,
  Active = 1,
  PendingScores = 2,
  ScoresUploaded = 3,
  ReadyForDeployment = 4,
  Failed = 5,
  Claimable = 6,
}

Error Handling

The SDK provides custom error classes for better error handling:

import {
  PresaleSDKError,
  InsufficientBalanceError,
  InsufficientAllowanceError,
  PresaleNotActiveError,
  PresaleNotClaimableError,
} from "@karma/presale-sdk";

try {
  await sdk.contribute({ presaleId, amount });
} catch (error) {
  if (error instanceof InsufficientBalanceError) {
    console.log("Not enough USDC balance");
  } else if (error instanceof InsufficientAllowanceError) {
    console.log("Need to approve USDC first");
  } else if (error instanceof PresaleNotActiveError) {
    console.log("Presale is not accepting contributions");
  }
}

Complete Example

import { createPublicClient, createWalletClient, http } from "viem";
import { mainnet } from "viem/chains";
import { privateKeyToAccount } from "viem/accounts";
import { KarmaPresaleSDK, PresaleStatus } from "@karma/presale-sdk";

async function participateInPresale() {
  // Setup
  const publicClient = createPublicClient({
    chain: mainnet,
    transport: http(),
  });

  const account = privateKeyToAccount(process.env.PRIVATE_KEY as `0x${string}`);
  const walletClient = createWalletClient({
    account,
    chain: mainnet,
    transport: http(),
  });

  const sdk = new KarmaPresaleSDK(
    {
      presaleContractAddress: process.env.PRESALE_ADDRESS as `0x${string}`,
      usdcAddress: process.env.USDC_ADDRESS as `0x${string}`,
      chainId: mainnet.id,
    },
    publicClient,
    walletClient
  );

  const presaleId = 1n;
  const userAddress = account.address;

  // 1. Check presale status
  const presale = await sdk.getPresale(presaleId);
  console.log(`Presale status: ${sdk.getPresaleStatusString(presale.status)}`);
  console.log(`Progress: ${sdk.getProgressPercentage(presale)}%`);
  console.log(`Time remaining: ${sdk.getTimeRemaining(presale)} seconds`);

  if (!sdk.isPresaleActive(presale)) {
    console.log("Presale is not active");
    return;
  }

  // 2. Check USDC balance
  const balance = await sdk.getUsdcBalance(userAddress);
  console.log(`USDC balance: ${sdk.formatUsdc(balance)}`);

  // 3. Contribute
  const contributionAmount = sdk.parseUsdc("1000");
  
  if (balance < contributionAmount) {
    console.log("Insufficient USDC balance");
    return;
  }

  console.log("Contributing to presale...");
  const result = await sdk.contributeWithApproval({
    presaleId,
    amount: contributionAmount,
  });
  const receipt = await result.wait();
  console.log(`Contribution successful! TX: ${receipt.transactionHash}`);

  // 4. Check contribution
  const contribution = await sdk.getContribution(presaleId, userAddress);
  console.log(`Total contribution: ${sdk.formatUsdc(contribution)} USDC`);

  // ... Later, after presale ends and tokens are deployed ...

  // 5. Claim tokens
  const presaleAfter = await sdk.getPresale(presaleId);
  if (sdk.isPresaleClaimable(presaleAfter)) {
    const allocation = await sdk.getTokenAllocation(presaleId, userAddress);
    console.log(`Token allocation: ${sdk.formatTokens(allocation)}`);

    if (allocation > 0n) {
      const claimResult = await sdk.claimTokens({ presaleId });
      await claimResult.wait();
      console.log("Tokens claimed successfully!");
    }

    // 6. Claim refund if any
    const refundAmount = await sdk.getRefundAmount(presaleId, userAddress);
    if (refundAmount > 0n) {
      console.log(`Refund available: ${sdk.formatUsdc(refundAmount)} USDC`);
      const refundResult = await sdk.claimRefund({ presaleId });
      await refundResult.wait();
      console.log("Refund claimed successfully!");
    }
  }
}

participateInPresale().catch(console.error);

Testing

# Run unit tests
npm test

# Run integration tests (requires local anvil node)
INTEGRATION=true npm test

Development

# Install dependencies
npm install

# Build
npm run build

# Lint
npm run lint

# Clean
npm run clean

License

MIT