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

@algorandfoundation/algoland-sdk

v1.1.0

Published

A TypeScript SDK for interacting with the Algoland smart contract on Algorand.

Readme

Algoland SDK

A TypeScript SDK for interacting with the Algoland smart contract on Algorand.

Installation

npm install @algorandfoundation/algoland-sdk

Requirements

Your package should install the peer requirements with the exact version matcher:

{
  "dependencies": {
    "@algorandfoundation/algokit-utils": "^9.0.0",
    "algosdk": "^3.0.0"
  }
}

Confirm the SDK's package.json for the latest peerDependencies.

Usage

Creating an SDK Instance

import { AlgolandSDK } from '@algorandfoundation/algoland-sdk';
import { AlgorandClient } from '@algorandfoundation/algokit-utils/types/algorand-client';

const appId = 3215540125n; // Mainnet contract App ID
const algorand = AlgorandClient.mainNet()

// Basic instantiation
const sdk = new AlgolandSDK({ appId, algorand });

Usage with @txnlab/use-wallet

import { useWallet } from '@txnlab/use-wallet';

const { algodClient, transactionSigner, activeAddress } = useWallet();
const algorand = AlgorandClient.fromClients({ algod: algodClient });
const sdk = new AlgolandSDK({ appId, algorand });

API Reference

Global State

Get the global state of the Algoland contract:

const globalState = await sdk.getGlobalState();
// Returns:
// {
//   admin: "ADMIN_ADDRESS_HERE...",
//   userCounter: 1234n,
//   drawAppId: 5678n,
//   backend: "BACKEND_ADDRESS_HERE..."
// }

User Methods

Get User by ID or Address

// Get user by ID
const userById = await sdk.getUser({ userId: 1n });
// Returns:
// {
//   address: "ABCDEF..FEDCBA",
//   relativeId: 1,
//   referrerId: 0,
//   numReferrals: 3,
//   referrals: [2, 5, 8],
//   points: 59,                        // 30 (own quests) + 9 (referral points) + 20 (redeemed back in)
//   redeemedPoints: 20,                // Points that were redeemed from prizes
//   completedQuests: [1, 2, 3],        // 3 completed quests = 30 points
//   completableChallenges: [2],
//   completedChallenges: [1],
//   weeklyDrawEligibility: [1],
//   availableDrawPrizeAssetIds: [123456n, 789012n],
//   claimedDrawPrizeAssetIds: [111111n],
//   displayPoints: 5900,               // 59 × 100
//   displayRedeemedPoints: 2000,       // 20 × 100
//   referralPoints: 9,                 // 59 - 30 (quest points) - 20 (redeemed) = 9
//   displayReferralPoints: 900         // 9 × 100
// }

// Get user by address
const userByAddress = await sdk.getUser({ userAddress: 'ABCDEF..FEDCBA' });
// Returns the same structure as above, or undefined if user not found

Get Multiple Users

const userAddresses = ['ADDRESS1', 'ADDRESS2', 'ADDRESS3'];
const usersMap = await sdk.getUsers({ userAddresses });
// Returns: Map<string, AlgolandUser | undefined>
// Map {
//   'ADDRESS1' => { address: 'ADDRESS1', relativeId: 1, ... },
//   'ADDRESS2' => undefined, // user not found
//   'ADDRESS3' => { address: 'ADDRESS3', relativeId: 5, ... }
// }

Get All Users

const allUsersMap = await sdk.getAllUsers();
// Returns: Map<string, AlgolandUser | undefined>
// Same structure as getUsers but contains all users registered in the system

Get User Referrals

// By user ID
const referrals = await sdk.getUserReferrals({ userId: 1 });
// Returns: string[]
// ['ADDRESS1', 'ADDRESS2', 'ADDRESS3']

// By user address
const referrals = await sdk.getUserReferrals({ userAddress: 'ADDRESS' });
// Returns: string[] - array of referral addresses

Quest Methods

Get All Quests

const questsMap = await sdk.getQuests();
// Returns: Map<number, AlgolandQuest>
// Map {
//   1 => { id: 1, name: "Complete First Challenge", challengeId: 1 },
//   2 => { id: 2, name: "Refer 5 Friends", challengeId: 2 },
//   3 => { id: 3, name: "Earn 100 Points", challengeId: 1 }
// }

Get Quest by ID

const quest = await sdk.getQuestById(1);
// Returns: AlgolandQuest | undefined
// { id: 1, name: "Complete First Challenge", challengeId: 1 }
// or undefined if quest not found

Challenge Methods

Get All Challenges

const challengesMap = await sdk.getChallenges();
// Returns: Map<number, AlgolandChallenge>
// Map {
//   1 => {
//     id: 1,
//     questIds: [1, 2],
//     completionBadgeAssetId: 123456n,
//     timeStart: 1640995200,
//     timeEnd: 1672531200,
//     numRequiredQuestsCompleted: 2,
//     drawPrizeAssetIds: [789012n],
//     numDrawEligibleAccounts: 100,
//     numDrawWinners: 10,
//     winners: [1, 5, 12, 23, 45]
//   }
// }

Get Challenge by ID

const challenge = await sdk.getChallengeById(1);
// Returns: AlgolandChallenge | undefined
// {
//   id: 1,
//   questIds: [1, 2],
//   completionBadgeAssetId: 123456n,
//   timeStart: 1640995200,
//   timeEnd: 1672531200,
//   numRequiredQuestsCompleted: 2,
//   drawPrizeAssetIds: [789012n],
//   numDrawEligibleAccounts: 100,
//   numDrawWinners: 10,
//   winners: [1, 5, 12, 23, 45]
// }
// or undefined if challenge not found

Transaction Methods

User Enrollment

Enroll a user into the campaign:

const { transactionSigner, activeAddress } = useWallet();

const result = await sdk.enrollCampaign({
  referrerId: 0n, // no referrer, or use a valid user ID
  sender: activeAddress,
  signer: transactionSigner,
});
// Returns: SendAppTransactionResult with transaction details and app return values
// {
//   transaction: Transaction,
//   confirmation: PendingTransactionResponse,
//   return: {
//     relativeId: 123,      // user's new relative ID
//     referrerId: 0,        // referrer ID (0 if no referrer)
//     numReferrals: 0,      // initial referral count
//     referrals: [],        // initial empty referrals array
//     points: 0,            // initial points
//     completedQuests: [],  // initial empty completed quests
//     completableChallenges: [], // challenges available to complete
//     completedChallenges: [],   // initial empty completed challenges
//     availableDrawPrizeAssetIds: [] // initial empty available prizes
//   }
// }

Complete Challenge

Complete a challenge and claim the badge:

const result = await sdk.completeChallenge({
  challengeId: 1,
  sender: activeAddress,
  signer: transactionSigner,
});
// Returns: SendAtomicTransactionComposerResults
// {
//   transactions: Transaction[],
//   confirmations: PendingTransactionResponse[],
//   returns: [], // void method returns empty array
//   txIds: ['TXN_ID_1', 'TXN_ID_2'] // may include asset opt-in transaction
// }

Admin Methods

Note: These methods require admin or backend permissions

Quest Management

// Complete a quest for a user (backend only)
const result = await sdk.completeQuest({
  questId: 1,
  user: 'USER_ADDRESS',
  sender: backendAddress,
  signer: backendSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

// Add a new quest (admin only)
const result = await sdk.addQuest({
  questId: 1,
  name: 'Quest Name',
  challengeId: 1,
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

// Delete a quest (admin only)
const result = await sdk.deleteQuest({
  questId: 1,
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

Challenge Management

// Add a new challenge (admin only)
const result = await sdk.addChallenge({
  challengeId: 1,
  challenge: challengeObject,
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

// Edit an existing challenge (admin only)
const result = await sdk.editChallenge({
  challengeId: 1,
  challenge: updatedChallengeObject,
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

// Delete a challenge (admin only)
const result = await sdk.deleteChallenge({
  challengeId: 1,
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

Asset Management

// Opt the contract into an asset (admin only)
const result = await sdk.optinAsset({
  asset: assetId,
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

// Opt in and send asset to contract (admin only)
const result = await sdk.optinAndSendAsset({
  asset: assetId,
  amount: 1000n,
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAtomicTransactionComposerResults
// {
//   transactions: Transaction[], // optin + transfer transactions
//   confirmations: PendingTransactionResponse[],
//   returns: [],
//   txIds: ['OPTIN_TXN_ID', 'TRANSFER_TXN_ID']
// }

Administrative Functions

// Change backend address (admin only)
const result = await sdk.changeBackend({
  newBackend: 'NEW_BACKEND_ADDRESS',
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

// Change admin address (admin only)
const result = await sdk.changeAdmin({
  newAdmin: 'NEW_ADMIN_ADDRESS',
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

// Change draw app ID (admin only)
const result = await sdk.changeDrawAppId({
  newDrawAppId: 5678n,
  sender: adminAddress,
  signer: adminSigner,
});
// Returns: SendAppTransactionResult (void method)
// { transaction: Transaction, confirmation: PendingTransactionResponse }

Types

The SDK exports all relevant types from the generated client and defines additional helper types:

import {
  AlgolandUser,
  AlgolandQuest,
  AlgolandChallenge,
  AlgolandGlobalState,
  DrawGlobalState,
  AlgolandWeeklyDrawState,
  NFTSpecWithCID,
  PointsNFTSpecWithCID
} from '@algorandfoundation/algoland-sdk';

Core Types

AlgolandUser

Represents a user in the Algoland system with all their quest progress and achievements:

type AlgolandUser = {
  address: string;                     // User's Algorand address
  relativeId: number;                  // Small incremental user ID (1, 2, 3...)
  referrerId: number;                  // RelativeId of the referrer
  numReferrals: number;                // Number of referrals
  referrals: number[];                 // Referrals' relative IDs
  points: number;                      // Accumulated points
  redeemedPoints: number;              // Redeemed points: points from redeeming Points prize assets
  completedQuests: number[];           // Individual quests completed
  completableChallenges: number[];     // Challenges that are ready to complete (by claiming NFT)
  completedChallenges: number[];       // Completed challenges
  weeklyDrawEligibility: number[];     // Weekly draw eligibility: completed challenges in time (values are challengeId)
  availableDrawPrizeAssetIds: bigint[]; // Available prizes (asset IDs) from weekly/final VRF draws
  claimedDrawPrizeAssetIds: bigint[];  // Claimed prizes (asset IDs) from weekly/final VRF draws

  // Computed properties (getters)
  displayPoints: number;               // Display-friendly points value (multiplied by display multiplier)
  displayRedeemedPoints: number;       // Display-friendly redeemed points value (multiplied by display multiplier)
  referralPoints: number;              // Points earned from referrals (total points minus own quest points and redeemed points)
  displayReferralPoints: number;       // Display-friendly referral points value (multiplied by display multiplier)
}

AlgolandQuest

Represents a quest that users can complete to earn points and progress in challenges:

type AlgolandQuest = {
  id: number;                   // Unique quest identifier
  name: string;                 // Human-readable quest name
  challengeId: number;          // ID of the challenge this quest belongs to
}

AlgolandChallenge

Represents a challenge that groups multiple quests and offers rewards:

type AlgolandChallenge = {
  id: number;                           // Unique challenge identifier
  questIds: number[];                   // Quest IDs for this challenge
  completionBadgeAssetId: bigint;       // Badge asset ID given out for completing the challenge (including after time end)
  timeStart: number;                    // Start time of challenge
  timeEnd: number;                      // End time of challenge. Only affects eligibility for weekly VRF draw. Challenge can be completed after this time
  numRequiredQuestsCompleted: number;   // Number of quest completions required to mark this challenge as complete. Usually equals to number of quests
  drawPrizeAssetIds: bigint[];          // Asset prize asset IDs for weekly draws
  numDrawEligibleAccounts: number;      // Tracks the number of accounts eligible for the weekly VRF draw
  numDrawWinners: number;               // Number of winners to be picked at the weekly VRF draw
  winners: number[];                    // Relative ID of weekly draw winners
}

AlgolandGlobalState

Represents the global state of the Algoland smart contract:

type AlgolandGlobalState = {
  admin: string;                // Address of the contract administrator
  userCounter: bigint;          // Total number of registered users
  drawAppId: bigint;            // App ID of the weekly draw contract
  backend: string;              // Address authorized to complete quests
}

DrawGlobalState

Represents the global state of the weekly draw smart contract:

type DrawGlobalState = {
  admin: string;                // Address of the draw contract administrator
  backend: string;              // Address authorized to operate the draw contract
  beaconAppId: bigint;          // App ID of the VRF beacon contract
  registryAppId: bigint;        // App ID of the main Algoland registry contract
}

AlgolandWeeklyDrawState

Represents the state of a weekly draw for a specific challenge:

type AlgolandWeeklyDrawState = {
  status: 'BLD' | 'RST' | 'RUN' | 'END';  // Build/Reset/Run/End status of the draw
  accountsIngested: bigint;               // Number of accounts processed for the draw
  lastRelativeId: bigint;                 // Last user relative ID processed
  commitBlocks: bigint[];                 // Block numbers used for VRF commit rounds
  winners: number[];                      // Relative IDs of draw winners
  txIds: Uint8Array[];                    // Transaction IDs associated with the draw
}

NFTSpecWithCID

Represents an NFT specification with optional IPFS CID:

type NFTSpecWithCID = {
  total: bigint;                // Total supply of the NFT
  assetName: string;            // Asset name
  unitName: string;             // Unit name
  url: string;                  // Asset URL
  freeze: string;               // Freeze address
  clawback: string;             // Clawback address
  reserve: string;              // Reserve address
  metadataHash: Uint8Array;     // Metadata hash (32 bytes)
  ipfsCid?: string;             // Optional IPFS CID for metadata
}

PointsNFTSpecWithCID

Represents an NFT specification for points-based assets:

type PointsNFTSpecWithCID = NFTSpecWithCID & {
  points: number;               // Points value associated with this NFT
}

Event Types

These types represent events emitted by the smart contract (useful for indexing and monitoring):

QuestCompletionEvent

Emitted when a user completes a quest:

type QuestCompletionEvent = {
  account: string;              // Address of the user completing the quest
  userId: number;               // Relative ID of the user
  questId: number;              // ID of the completed quest
  challengeId: number;          // ID of the challenge the quest belongs to
}

ChallengeCompletableEvent

Emitted when a user becomes eligible to complete a challenge:

type ChallengeCompletableEvent = {
  account: string;              // Address of the user
  userId: number;               // Relative ID of the user
  challengeId: number;          // ID of the challenge now available to complete
}

ChallengeCompletedEvent

Emitted when a user completes a challenge and claims the NFT:

type ChallengeCompletedEvent = {
  account: string;              // Address of the user
  userId: number;               // Relative ID of the user
  challengeId: number;          // ID of the completed challenge
}

PointsEvent

Emitted when points are awarded to a user:

type PointsEvent = {
  account: string;              // Address of the user receiving points
  userId: number;               // Relative ID of the user receiving points
  questId: number;              // ID of the quest that generated the points
  addedPoints: number;          // Number of points added in this event
  totalPoints: number;          // User's total points after this addition
  actorUserId: number;          // ID of the user who triggered the points:
                               // - If points from own completion: actorUserId === userId
                               // - If referral points: actorUserId = referred user, userId = referrer
}

Type Usage Examples

Working with Users

const user: AlgolandUser = await sdk.getUser({ userId: 1n });

if (user) {
  console.log(`User ${user.address} has ${user.points} points (display: ${user.displayPoints})`);
  // Output: User ABCDEF..FEDCBA has 59 points (display: 5900)
  
  console.log(`Completed quests: ${user.completedQuests.join(', ')}`);
  // Output: Completed quests: 1, 2, 3
  
  console.log(`Ready to claim challenges: ${user.completableChallenges.join(', ')}`);
  // Output: Ready to claim challenges: 2
  
  console.log(`Completed challenges: ${user.completedChallenges.join(', ')}`);
  // Output: Completed challenges: 1
  
  // Check points breakdown
  console.log(`Total display points: ${user.displayPoints}`);
  // Output: Total display points: 5900
  
  console.log(`Referral display points: ${user.displayReferralPoints}`);
  // Output: Referral display points: 900
  
  console.log(`Redeemed display points: ${user.displayRedeemedPoints}`);
  // Output: Redeemed display points: 2000
  
  // Check weekly draw eligibility
  if (user.weeklyDrawEligibility.length > 0) {
    console.log(`Eligible for weekly draws: ${user.weeklyDrawEligibility.join(', ')}`);
    // Output: Eligible for weekly draws: 1
  }
  
  // Check available prizes
  if (user.availableDrawPrizeAssetIds.length > 0) {
    console.log(`Available prizes: ${user.availableDrawPrizeAssetIds.join(', ')}`);
    // Output: Available prizes: 123456, 789012
  }

  // Check if user has referrals
  if (user.numReferrals > 0) {
    console.log(`User has referred ${user.numReferrals} users`);
    // Output: User has referred 3 users
    
    const referralAddresses = await sdk.getUserReferrals({ userId: user.relativeId });
    console.log(`Referral addresses: ${referralAddresses.join(', ')}`);
    // Output: Referral addresses: ADDRESS1, ADDRESS2, ADDRESS3
  }
}

Working with Challenges

const challenge: AlgolandChallenge = await sdk.getChallengeById(1);

if (challenge) {
  const now = Math.floor(Date.now() / 1000);
  const isActive = now >= challenge.timeStart && now <= challenge.timeEnd;

  console.log(`Challenge "${challenge.id}" is ${isActive ? 'active' : 'inactive'}`);
  console.log(`Requires ${challenge.numRequiredQuestsCompleted} quests to complete`);
  console.log(`Completion badge: Asset ID ${challenge.completionBadgeAssetId}`);

  if (challenge.winners.length > 0) {
    console.log(`Draw winners: ${challenge.winners.join(', ')}`);
  }
}

Error Handling

All async methods may throw errors. It's recommended to wrap calls in try-catch blocks:

try {
  const user = await sdk.getUser({ userId: 1n });
  console.log('User found:', user);
} catch (error) {
  console.error('Failed to get user:', error.message);
}