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

@verxioprotocol/core

v0.1.3

Published

Opensource infrastructure powering on-chain loyalty across Solana with Metaplex Core

Readme

Verxio Protocol

On-chain loyalty infrastructure for creating and managing loyalty programs on solana and SVM.

Features

Core Loyalty System

  • Create loyalty programs with custom tiers and rewards
  • Issue loyalty passes as NFTs with automatic metadata generation or custom metadata
  • Track user XP and tier progression with automatic tier updates
  • Support for transferable loyalty passes (with organization approval)
  • Built-in support for multiple networks (Solana, Sonic)
  • Automatic tier progression based on XP accumulation
  • Update loyalty program tiers and points per action dynamically
  • Gift points to users with custom actions and reasons
  • Comprehensive asset data and customer behavior tracking
  • Flexible authority management for loyalty programs and loyalty pass updates

Communication & Messaging

  • Direct messaging between program and pass holders
  • Program-wide broadcasts with targeted delivery options
  • Message read status tracking and analytics
  • Rich message metadata with timestamps and sender information

Advanced Transaction Composition

  • Instruction-based functions for advanced transaction batching
  • Custom fee handling and gas optimization
  • Transaction composition with multiple operations
  • Built-in protocol fees with transparent cost structure

Complete Voucher Management System

  • Create, mint, validate, and redeem vouchers with full lifecycle management
  • Voucher Collections - Organize vouchers by merchant and type
  • Voucher Analytics - Track redemption rates, usage patterns, and performance metrics
  • User Voucher Management - Get user vouchers with filtering and sorting
  • Merchant Voucher Operations - Bulk operations and merchant-specific analytics
  • Voucher Validation - Comprehensive validation with expiry and usage tracking
  • Voucher Redemption - Multi-type voucher redemption with value calculation
  • Voucher Expiry Management - Extend or cancel vouchers with reason tracking
  • Merchant Identification - Flexible merchant ID system for off-chain integration

Supported Voucher Types

  • Percentage Off Vouchers - Dynamic discounts based on purchase amount
  • Fixed Credit Vouchers - Fixed value credits for any purchase
  • Free Item Vouchers - Free items up to specified value
  • Buy One Get One Vouchers - BOGO promotions with value limits
  • Custom Reward Vouchers - Flexible reward structures

Advanced Features

  • Irys Integration - Automatic NFT image and metadata uploads
  • Comprehensive Test Suite - Full coverage with 100+ test cases
  • Robust Error Handling - Detailed validation and error messages
  • Type Safety - Full TypeScript support with comprehensive types
  • Performance Optimized - Efficient blockchain operations and data structures

Installation

npm install @verxioprotocol/core
# or
yarn add @verxioprotocol/core
# or
pnpm add @verxioprotocol/core

Quick Start

Initialize Protocol

import { initializeVerxio } from '@verxioprotocol/core'
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { publicKey, keypairIdentity } from '@metaplex-foundation/umi'

// Create UMI instance (Solana & SVM supported)
const umi = createUmi('RPC_URL')

// Add Irys uploader for metadata/image uploads (Optional)
umi.use(irysUploader())

// Initialize program
const context = initializeVerxio(
  umi,
  publicKey('PROGRAM_AUTHORITY'), // Program authority public key
)

// Set Signer
context.umi.use(keypairIdentity('FEE_PAYER'))

Create Your First Loyalty Program

import { createLoyaltyProgram } from '@verxioprotocol/core'

const result = await createLoyaltyProgram(context, {
  loyaltyProgramName: 'Coffee Brew Rewards',
  metadataUri: 'https://arweave.net/...',
  programAuthority: context.programAuthority,
  metadata: {
    organizationName: 'Coffee Brew', // Required
    brandColor: '#FF5733', // Optional: for UI customization
  },
  tiers: [
    { name: 'Bronze', xpRequired: 500, rewards: ['2% cashback'] },
    { name: 'Silver', xpRequired: 1000, rewards: ['5% cashback'] },
    { name: 'Gold', xpRequired: 2000, rewards: ['10% cashback'] },
  ],
  pointsPerAction: {
    purchase: 100,
    review: 50,
    referral: 200,
  },
})

console.log('Loyalty Program Created:', result.collection.publicKey)

Two Approaches to Using Verxio Protocol

Verxio Protocol provides two complementary approaches for different use cases:

1. Direct Functions (Immediate Execution)

Traditional functions that execute transactions immediately - perfect for simple, single-operation use cases.

2. Instruction Functions (Advanced Composition)

Instruction-based functions that return TransactionBuilder objects for advanced transaction composition, batching, and custom fee handling.


Direct Functions Usage

Initialize Protocol

import { initializeVerxio } from '@verxioprotocol/core'
import { createUmi } from '@metaplex-foundation/umi-bundle-defaults'
import { publicKey } from '@metaplex-foundation/umi'

// Create UMI instance (Solana & SVM supported)
const umi = createUmi('RPC_URL')

// Initialize program
const context = initializeVerxio(
  umi,
  publicKey('PROGRAM_AUTHORITY'), // Program authority public key
)

// Set Signer
context.umi.use(keypairIdentity('FEE_PAYER'))

Create Loyalty Program

You can either:

  • Provide a pre-uploaded metadata URI (no image upload needed), or
  • Provide an image buffer and filename to auto-upload the image and generate metadata.

1. Using a pre-uploaded metadata URI

const result = await createLoyaltyProgram(context, {
  loyaltyProgramName: 'Coffee Brew Rewards',
  metadataUri: 'https://arweave.net/...', // Already uploaded metadata
  programAuthority: context.programAuthority,
  updateAuthority: generateSigner(context.umi), // Optional: Provide custom update authority
  metadata: {
    organizationName: 'Coffee Brew', // Required: Name of the host/organization
    brandColor: '#FF5733', // Optional: Brand color for UI customization
  },
  tiers: [
    {
      name: 'Bronze',
      xpRequired: 500,
      rewards: ['2% cashback'],
    },
    {
      name: 'Silver',
      xpRequired: 1000,
      rewards: ['5% cashback'],
    },
  ],
  pointsPerAction: {
    purchase: 100,
    review: 50,
  },
})

console.log(result)
// {
//   collection: KeypairSigner,  // Collection signer
//   signature: string,         // Transaction signature
//   programAuthority: KeypairSigner // Update authority for the loyalty program
// }

2. Uploading an image and generating metadata

const fs = require('fs')
const imageBuffer = fs.readFileSync('logo.png')
const result = await createLoyaltyProgram(context, {
  loyaltyProgramName: 'Coffee Brew Rewards',
  imageBuffer, // Buffer of your image
  imageFilename: 'logo.png',
  programAuthority: context.programAuthority,
  updateAuthority: generateSigner(context.umi), // Optional: Provide custom update authority
  metadata: {
    organizationName: 'Coffee Brew', // Required: Name of the host/organization
    brandColor: '#FF5733', // Optional: Brand color for UI customization
  },
  tiers: [
    {
      name: 'Bronze',
      xpRequired: 500,
      rewards: ['2% cashback'],
    },
    {
      name: 'Silver',
      xpRequired: 1000,
      rewards: ['5% cashback'],
    },
  ],
  pointsPerAction: {
    purchase: 100,
    review: 50,
  },
})
// The protocol will upload the image, generate metadata, and use the resulting URI

Update Loyalty Program

// Update points per action
const result = await updateLoyaltyProgram(context, {
  collectionAddress: publicKey('COLLECTION_ADDRESS'),
  programAuthority: context.programAuthority,
  updateAuthority: programAuthority, // Required: Program authority from Loyalty Program creation
  newPointsPerAction: {
    purchase: 150, // Update existing action
    referral: 200, // Add new action
  },
})

// Update tiers
const result = await updateLoyaltyProgram(context, {
  collectionAddress: publicKey('COLLECTION_ADDRESS'),
  programAuthority: context.programAuthority,
  updateAuthority: programAuthority, // Required: Program authority from Loyalty Program creation
  newTiers: [
    { name: 'Grind', xpRequired: 0, rewards: ['nothing for you!'] }, // Grind tier must exist
    { name: 'Bronze', xpRequired: 400, rewards: ['free item'] }, // Update existing tier
    { name: 'Silver', xpRequired: 1000, rewards: ['5% cashback'] },
    { name: 'Gold', xpRequired: 2000, rewards: ['10% cashback'] },
    { name: 'Platinum', xpRequired: 5000, rewards: ['20% cashback'] }, // Add new tier
  ],
})

// Update both tiers and points per action
const result = await updateLoyaltyProgram(context, {
  collectionAddress: publicKey('COLLECTION_ADDRESS'),
  programAuthority: context.programAuthority,
  updateAuthority: programAuthority, // Required: Program authority from Loyalty Program creation
  newTiers: [
    { name: 'Grind', xpRequired: 0, rewards: ['nothing for you!'] },
    { name: 'Bronze', xpRequired: 400, rewards: ['free item'] },
    { name: 'Silver', xpRequired: 1000, rewards: ['5% cashback'] },
    { name: 'Gold', xpRequired: 2000, rewards: ['10% cashback'] },
  ],
  newPointsPerAction: {
    purchase: 150,
    referral: 200,
  },
})

console.log(result)
// {
//   signature: string  // Transaction signature
// }

Issue Loyalty Pass

You can either:

  • Provide a pre-uploaded metadata URI (no image upload needed), or
  • Provide an image buffer and filename to auto-upload the image and generate metadata.

1. Using a pre-uploaded metadata URI

const result = await issueLoyaltyPass(context, {
  collectionAddress: context.collectionAddress,
  recipient: publicKey('RECIPIENT_ADDRESS'),
  passName: 'Coffee Rewards Pass',
  passMetadataUri: 'https://arweave.net/...', // Already uploaded metadata
  assetSigner: generateSigner(context.umi), // Optional: Provide a signer for the pass
  updateAuthority: programAuthority, // Required: Program authority of the Loyalty Program
  organizationName: 'Coffee Brew',
})

console.log(result)
// {
//   asset: KeypairSigner,  // Pass signer
//   signature: string      // Transaction signature
// }

2. Uploading an image and generating metadata

const imageBuffer = fs.readFileSync('pass.png')
const result = await issueLoyaltyPass(context, {
  collectionAddress: context.collectionAddress,
  recipient: publicKey('RECIPIENT_ADDRESS'),
  passName: 'Coffee Rewards Pass',
  imageBuffer, // Buffer of your image
  imageFilename: 'pass.png',
  updateAuthority: programAuthority, // Required: Program authority of the Loyalty Program
  organizationName: 'Coffee Brew',
})
// The protocol will upload the image, generate metadata, and use the resulting URI

Award Points

const result = await awardLoyaltyPoints(context, {
  passAddress: publicKey('PASS_ADDRESS'),
  action: 'purchase',
  signer: programAuthority, // Required: Program authority of the Loyalty Program
  multiplier: 1, // Optional: Point multiplier (default: 1)
})

console.log(result)
// {
//   points: number,    // New total points
//   signature: string  // Transaction signature
//   newTier: LoyaltyProgramTier // New tier if updated
// }

Revoke Points

const result = await revokeLoyaltyPoints(context, {
  passAddress: publicKey('PASS_ADDRESS'),
  pointsToRevoke: 50,
  signer: programAuthority, // Required: Program authority of the Loyalty Program
})

console.log(result)
// {
//   points: number,    // New total points after reduction
//   signature: string  // Transaction signature
//   newTier: LoyaltyProgramTier // New tier if updated
// }

Gift Points

const result = await giftLoyaltyPoints(context, {
  passAddress: publicKey('PASS_ADDRESS'),
  pointsToGift: 100,
  signer: updateAuthority, // Required: Program authority of the Loyalty Program
  action: 'bonus', // Reason for gifting points
})

console.log(result)
// {
//   points: number,    // New total points
//   signature: string  // Transaction signature
//   newTier: LoyaltyProgramTier // New tier if updated
// }

Get Asset Data

const assetData = await getAssetData(context, publicKey('PASS_ADDRESS'))

console.log(assetData)
// {
//   xp: number,              // Current XP points
//   lastAction: string | null, // Last action performed
//   actionHistory: Array<{   // History of actions
//     type: string,
//     points: number,
//     timestamp: number,
//     newTotal: number
//   }>,
//   currentTier: string,     // Current tier name
//   tierUpdatedAt: number,   // Timestamp of last tier update
//   rewards: string[],       // Available rewards
//   name: string,           // Asset name
//   uri: string,            // Asset metadata URI
//   owner: string,          // Asset owner address
//   pass: string,           // Pass public key
//   metadata: {             // Program metadata
//     organizationName: string,     // Required: Name of the host/organization
//     brandColor?: string   // Optional: Brand color for UI customization
//   },
//   rewardTiers: Array<{    // All available reward tiers
//     name: string,
//     xpRequired: number,
//     rewards: string[]
//   }>
// }

Get Program Details

const programDetails = await getProgramDetails(context)

console.log(programDetails)
// {
//   name: string,
//   uri: string,
//   collectionAddress: string,
//   updateAuthority: string,
//   numMinted: number,
//   creator: string,
//   tiers: Array<{
//     name: string,
//     xpRequired: number,
//     rewards: string[]
//   }>,
//   pointsPerAction: Record<string, number>,
//   metadata: {
//     organizationName: string,     // Required: Name of the host/organization
//     brandColor?: string   // Optional: Brand color for UI customization
//   }
// }

Get Wallet Loyalty Passes

const passes = await getWalletLoyaltyPasses(context, publicKey('WALLET_ADDRESS'))

console.log(passes)
// Array<{
//   publicKey: string,
//   name: string,
//   uri: string,
//   owner: string
// }>

Get Program Tiers

const tiers = await getProgramTiers(context)

console.log(tiers)
// Array<{
//   name: string,
//   xpRequired: number,
//   rewards: string[]
// }>

Get Points Per Action

const pointsPerAction = await getPointsPerAction(context)

console.log(pointsPerAction)
// Record<string, number> // Action name to points mapping

Approve Transfer

await approveTransfer(context, {
  passAddress: publicKey('PASS_ADDRESS'),
  toAddress: publicKey('NEW_OWNER_ADDRESS'),
})

Send Message

const result = await sendMessage(context, {
  passAddress: publicKey('PASS_ADDRESS'),
  message: 'Welcome to our loyalty program!',
  sender: programAuthority.publicKey,
  signer: updateAuthority, // Required: Program authority of the Loyalty Program
})

console.log(result)
// {
//   signature: string,  // Transaction signature
//   message: {
//     id: string,      // Unique message ID
//     content: string, // Message content
//     sender: string,  // Sender's public key
//     timestamp: number, // Message timestamp
//     read: boolean    // Message read status
//   }
// }

Mark Message as Read

const result = await markMessageRead(context, {
  passAddress: publicKey('PASS_ADDRESS'),
  messageId: 'MESSAGE_ID',
  signer: updateAuthority, // Required: Program authority of the Loyalty Program
})

console.log(result)
// {
//   signature: string  // Transaction signature
// }

Get Asset Messages

const messages = await getAssetMessages(context, publicKey('PASS_ADDRESS'))

console.log(messages)
// {
//   stats: {
//     total: number,   // Total number of messages
//     unread: number,  // Number of unread messages
//     read: number     // Number of read messages
//   },
//   messages: Array<{
//     id: string,      // Message ID
//     content: string, // Message content
//     sender: string,  // Sender's public key
//     timestamp: number, // Message timestamp
//     read: boolean    // Message read status
//   }>
// }

Send Broadcast

// Send broadcast to all holders
const result = await sendBroadcast(context, {
  collectionAddress: publicKey('COLLECTION_ADDRESS'),
  message: 'Welcome to our loyalty program!',
  sender: programAuthority.publicKey,
  signer: updateAuthority, // Required: Program authority of the Loyalty Program
})

// Send broadcast to specific holders
const specificResult = await sendBroadcast(context, {
  collectionAddress: publicKey('COLLECTION_ADDRESS'),
  message: 'VIP announcement',
  sender: programAuthority.publicKey,
  signer: updateAuthority,
})

console.log(result)
// {
//   signature: string,  // Transaction signature
//   broadcast: {
//     id: string,      // Unique broadcast ID
//     content: string, // Broadcast content
//     sender: string,  // Sender's public key
//     timestamp: number, // Broadcast timestamp
//     read: boolean,   // Broadcast read status
//     recipients?: {   // Optional recipient information
//       type: 'all' | 'tier' | 'specific',
//       value?: string[] // For 'tier': tier names, For 'specific': holder addresses
//     }
//   }
// }

Mark Broadcast as Read

const result = await markBroadcastRead(context, {
  collectionAddress: publicKey('COLLECTION_ADDRESS'),
  broadcastId: 'BROADCAST_ID',
  signer: updateAuthority, // Required: Program authority of the Loyalty Program
})

console.log(result)
// {
//   signature: string  // Transaction signature
// }

Get Program Broadcasts

const broadcasts = await getProgramDetails(context)

console.log(broadcasts.broadcasts)
// {
//   broadcasts: Array<{
//     id: string,      // Broadcast ID
//     content: string, // Broadcast content
//     sender: string,  // Sender's public key
//     timestamp: number, // Broadcast timestamp
//     read: boolean,   // Broadcast read status
//     recipients?: {   // Optional recipient information
//       type: 'all' | 'tier' | 'specific',
//       value?: string[] // For 'tier': tier names, For 'specific': holder addresses
//     }
//   }>,
//   totalBroadcasts: number // Total number of broadcasts
// }

Voucher Management System

Verxio Protocol includes a comprehensive voucher management system for creating, distributing, and redeeming digital vouchers with full lifecycle management.

Create Voucher Collection

You can either:

  • Provide a pre-uploaded metadata URI (no image upload needed), or
  • Provide an image buffer and filename to auto-upload the image and generate metadata.

1. Using a pre-uploaded metadata URI

const result = await createVoucherCollection(context, {
  collectionName: 'Summer Sale Vouchers',
  collectionMetadataUri: 'https://arweave.net/...', // Already uploaded metadata
  updateAuthority: generateSigner(context.umi),
  metadata: {
    merchantName: 'Coffee Brew',
    description: 'Summer sale vouchers for loyal customers',
    terms: 'Valid until August 31st, 2024',
  },
})

console.log(result)
// {
//   collection: KeypairSigner,  // Collection signer
//   signature: string,         // Transaction signature
//   updateAuthority: KeypairSigner // Update authority for the collection
// }

2. Uploading an image and generating metadata

const imageBuffer = fs.readFileSync('voucher-collection.png')
const result = await createVoucherCollection(context, {
  collectionName: 'Summer Sale Vouchers',
  imageBuffer, // Buffer of your image
  imageFilename: 'voucher-collection.png',
  updateAuthority: generateSigner(context.umi),
  metadata: {
    merchantName: 'Coffee Brew',
    description: 'Summer sale vouchers for loyal customers',
    terms: 'Valid until August 31st, 2024',
  },
})
// The protocol will upload the image, generate metadata, and use the resulting URI

Mint Voucher

You can either:

  • Provide a pre-uploaded metadata URI (no image upload needed), or
  • Provide an image buffer and filename to auto-upload the image and generate metadata.

1. Using a pre-uploaded metadata URI

const result = await mintVoucher(context, {
  collectionAddress: publicKey('COLLECTION_ADDRESS'),
  voucherName: 'Summer Sale Voucher',
  voucherMetadataUri: 'https://arweave.net/...', // Already uploaded metadata
  voucherData: {
    type: 'percentage_off',
    value: 15, // 15% off
    maxUses: 1,
    expiryDate: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days from now
    conditions: [{ type: 'minimum_purchase', value: 50, operator: 'greater_than' }],
    description: '15% off your next purchase',
    merchantId: 'coffee_brew_merchant_001', // String identifier for the merchant
  },
  recipient: publicKey('RECIPIENT_ADDRESS'),
  updateAuthority: generateSigner(context.umi),
})

console.log(result)
// {
//   asset: KeypairSigner,  // Voucher signer
//   signature: string,    // Transaction signature
//   voucherAddress: PublicKey // Voucher public key
// }

2. Uploading an image and generating metadata

const imageBuffer = fs.readFileSync('voucher.png')
const result = await mintVoucher(context, {
  collectionAddress: publicKey('COLLECTION_ADDRESS'),
  voucherName: 'Summer Sale Voucher',
  imageBuffer, // Buffer of your image
  imageFilename: 'voucher.png',
  voucherData: {
    type: 'percentage_off',
    value: 15, // 15% off
    maxUses: 1,
    expiryDate: Date.now() + 30 * 24 * 60 * 60 * 1000, // 30 days from now
    conditions: [{ type: 'minimum_purchase', value: 50, operator: 'greater_than' }],
    description: '15% off your next purchase',
    merchantId: 'coffee_brew_merchant_001', // String identifier for the merchant
  },
  recipient: publicKey('RECIPIENT_ADDRESS'),
  updateAuthority: generateSigner(context.umi),
})
// The protocol will upload the image, generate metadata, and use the resulting URI

Validate Voucher

const validation = await validateVoucher(context, {
  voucherAddress: publicKey('VOUCHER_ADDRESS'),
})

console.log(validation)
// {
//   isValid: boolean,
//   errors: string[],
//   warnings: string[],
//   voucherData: {
//     type: string,
//     value: number,
//     currentUses: number,
//     maxUses: number,
//     expiryDate: number,
//     conditions: string[],
//     description: string,
//     merchantId: string
//   },
//   redemptionValue: number
// }

Redeem Voucher

The redeemVoucher function performs comprehensive validation and redemption of vouchers. It enforces merchant ID matching, validates expiry dates, usage limits, and conditions, then records the redemption in the voucher's history.

const result = await redeemVoucher(context, {
  voucherAddress: publicKey('VOUCHER_ADDRESS'),
  merchantId: 'coffee_brew_merchant_001', // String identifier for the merchant
  updateAuthority: generateSigner(context.umi), // Authority that can update the voucher
  redemptionAmount: 100, // Purchase amount for percentage-based vouchers
  redemptionDetails: {
    transactionId: 'tx_123',
    items: ['Coffee', 'Pastry'],
    totalAmount: 100,
    discountApplied: 25,
  },
})

console.log(result)
// {
//   instruction: TransactionBuilder, // Transaction instruction for execution
//   validation: {
//     errors: string[], // Validation errors if any
//     voucher: VoucherData // Voucher data after validation
//   },
//   redemptionValue: number, // Calculated redemption value
//   updatedVoucher: VoucherData // Voucher data after redemption
// }

Get User Vouchers

const vouchers = await getUserVouchers(context, {
  userAddress: publicKey('USER_ADDRESS'),
  filters: {
    status: 'active', // 'active' | 'expired' | 'fully_used'
    type: 'percentage_off', // Optional: filter by voucher type
    minValue: 10, // Optional: minimum value
  },
  sortBy: 'expiryDate', // 'expiryDate' | 'value' | 'createdAt'
  sortOrder: 'asc', // 'asc' | 'desc'
  limit: 10, // Optional: limit results
})

console.log(vouchers)
// {
//   vouchers: Array<{
//     address: string,
//     type: string,
//     value: number,
//     currentUses: number,
//     maxUses: number,
//     expiryDate: number,
//     status: string,
//     description: string,
//     conditions: string[],
//     collection: string
//   }>,
//   total: number,
//   expiringSoon: Array<string>, // Voucher addresses expiring in 7 days
//   redeemable: Array<string>    // Voucher addresses that can be redeemed
// }

Extend Voucher Expiry

const result = await extendVoucherExpiry(context, {
  voucherAddress: publicKey('VOUCHER_ADDRESS'),
  newExpiryDate: Date.now() + 60 * 24 * 60 * 60 * 1000, // 60 days from now
  reason: 'Customer request',
  signer: generateSigner(context.umi),
})

console.log(result)
// {
//   signature: string,
//   newExpiryDate: number
// }

Cancel Voucher

const result = await cancelVoucher(context, {
  voucherAddress: publicKey('VOUCHER_ADDRESS'),
  reason: 'Customer refund',
  signer: generateSigner(context.umi),
})

console.log(result)
// {
//   signature: string,
//   status: 'cancelled'
// }

Merchant Identification

In the voucher system, merchants are identified using a merchantId string rather than a blockchain address. This provides flexibility for:

  • Off-chain Integration: Merchants can use their existing business identifiers
  • Multi-chain Support: Same merchant can operate across different networks
  • Privacy: Merchant identity can be managed separately from blockchain addresses
  • Scalability: No need to manage multiple wallet addresses per merchant

The merchantId is set when creating vouchers and validated during redemption to ensure vouchers are only used at the correct merchant.

Supported Voucher Types

Verxio Protocol supports multiple voucher types for different use cases:

Percentage Off Vouchers

{
  type: 'percentage_off',
  value: 15, // 15% discount
  conditions: ['Minimum purchase: $50']
}

Fixed Credit Vouchers

{
  type: 'fixed_verxio_credits',
  value: 100, // $100 in credits
  conditions: ['Valid for any purchase']
}

Free Item Vouchers

{
  type: 'free_item',
  value: 25, // $25 item value
  conditions: ['Valid for items up to $25']
}

Buy One Get One Vouchers

{
  type: 'buy_one_get_one',
  value: 30, // Free item worth $30
  conditions: ['Buy any item, get one free up to $30']
}

Custom Reward Vouchers

{
  type: 'custom_reward',
  value: 50, // Custom value
  conditions: ['Special promotion', 'Valid with other offers']
}

Instruction Functions Usage (Advanced)

Instruction-based functions provide advanced transaction composition capabilities, allowing you to batch multiple operations, optimize fees, and integrate with existing transaction flows.

Key Benefits

  • Composability: Combine multiple Verxio operations in a single transaction
  • Flexibility: Add custom instructions before/after Verxio operations
  • Gas Optimization: Batch operations to save on transaction fees
  • Integration: Easier integration with existing transaction flows
  • Error Handling: Validate inputs before transaction execution

Protocol Fees

Verxio Protocol includes built-in static fees for protocol operations:

  • CREATE_LOYALTY_PROGRAM: 0.002 SOL - Creating new loyalty programs
  • LOYALTY_OPERATIONS: 0.001 SOL - Pass issuance and program updates
  • VERXIO_INTERACTION: 0.0004 SOL - Points management and messaging
  • VOUCHER_OPERATIONS: 0.0008 SOL - Voucher creation, minting, and redemption
  • VOUCHER_MANAGEMENT: 0.0006 SOL - Voucher validation and analytics

All instruction functions include these fees by default.

Basic Instruction Usage

import { createLoyaltyProgramInstruction } from '@verxioprotocol/core'

// Create instruction (doesn't execute)
const { instruction, collection, updateAuthority } = createLoyaltyProgramInstruction(context, config)

// Execute when ready
const result = await instruction.sendAndConfirm(context.umi)

Composing Multiple Operations

import {
  createLoyaltyProgramInstruction,
  issueLoyaltyPassInstruction,
  awardLoyaltyPointsInstruction,
} from '@verxioprotocol/core'

// Create individual instructions
const { instruction: createProgram, collection } = createLoyaltyProgramInstruction(context, programConfig)
const { instruction: issuePass } = issueLoyaltyPassInstruction(context, passConfig)
const { instruction: awardPoints } = await awardLoyaltyPointsInstruction(context, pointsConfig)

// Combine into single transaction
const combinedTx = createProgram.add(issuePass).add(awardPoints).add(customInstruction) // Your own instruction

// Execute with custom settings
const result = await combinedTx.sendAndConfirm(context.umi, {
  confirm: { commitment: 'finalized' },
  send: { skipPreflight: true },
})

Available Instruction Functions

Core Loyalty Program Operations

  • createLoyaltyProgramInstruction - Create a new loyalty program
  • updateLoyaltyProgramInstruction - Update existing loyalty program
  • issueLoyaltyPassInstruction - Issue loyalty passes to users

Points Management

  • awardLoyaltyPointsInstruction - Award points for actions
  • `