Learn how to effectively manage points and currencies in your DRIP realm. This guide covers everything from basic point operations to advanced currency management strategies. 
Overview  
DRIP’s point system is highly flexible, allowing you to create multiple currencies, manage complex reward structures, and build engaging gamification experiences for your community. 
Points in DRIP are called “Realm Points” and can be customized with names, emojis, and branding to match your community’s theme. 
 
Understanding Realm Points  
Point Types  
Primary Currency Your main point system (e.g., XP, Coins, Tokens) 
Usually the most visible to members 
Used for major rewards and purchases 
Often tied to overall member ranking 
 
Secondary Currencies Additional point types for specific purposes 
Event-specific points (e.g., “Summer Points”) 
Category-specific rewards (e.g., “Art Coins”) 
Premium currencies (e.g., “Gems”) 
  
Point Properties  
Each Realm Point has these key properties: 
const  realmPoint  = {  
  id:  "507f1f77bcf86cd799439015" ,  
  name:  "Community XP" ,  
  emoji:  "⭐" ,  
  description:  "Experience points for community participation" ,  
  isDefault:  true ,  
  isTransferable:  true ,  
  minimumBalance:  0 ,  
  maximumBalance:  1000000  
};  
 
Basic Point Operations  
Awarding Points  
async  function  awardPoints ( client ,  memberId ,  points ,  reason  =  '' ) {  
  try  {  
    const  result  =  await  client . request ( 'PATCH' ,   
      `/realm/ ${ client . realmId } /members/ ${ memberId } /point-balance` ,  
      {  tokens:  points  }  
    );  
      
    console . log ( `✅ Awarded  ${ points }  points to member  ${ memberId } ` );  
    if  ( reason )  console . log ( `Reason:  ${ reason } ` );  
      
    return  result ;  
  }  catch  ( error ) {  
    console . error ( `❌ Failed to award points:  ${ error . message } ` );  
    throw  error ;  
  }  
}  
 
// Examples  
await  awardPoints ( client ,  'member123' ,  100 ,  'Completed daily quest' );  
await  awardPoints ( client ,  'member456' ,  50 ,  'Helpful community contribution' );  
 
Deducting Points  
// Deduct points (negative amount)  
await  awardPoints ( client ,  'member123' , - 25 ,  'Minor rule violation penalty' );  
 
// Or use a dedicated deduction function  
async  function  deductPoints ( client ,  memberId ,  points ,  reason  =  '' ) {  
  return  await  awardPoints ( client ,  memberId , - Math . abs ( points ),  reason );  
}  
 
Checking Balances  
async  function  getPointBalance ( client ,  memberId ) {  
  const  members  =  await  client . searchMembers ( 'drip-id' ,  memberId );  
    
  if  ( members . data  &&  members . data . length  >  0 ) {  
    const  member  =  members . data [ 0 ];  
    return  member . pointBalances  || [];  
  }  
    
  throw  new  Error ( 'Member not found' );  
}  
 
// Usage  
const  balances  =  await  getPointBalance ( client ,  'member123' );  
balances . forEach ( balance  =>  {  
  console . log ( ` ${ balance . realmPoint . name } :  ${ balance . balance }  ${ balance . realmPoint . emoji } ` );  
});  
 
Advanced Point Management  
Multiple Currency Systems  
Manage different types of points for different purposes: 
class  MultiCurrencyManager  {  
  constructor ( client ) {  
    this . client  =  client ;  
    this . currencies  =  new  Map ();  
  }  
 
  async  loadCurrencies () {  
    // Load available realm points  
    const  realmPoints  =  await  this . client . getRealmPoints ();  
      
    for  ( const  point  of  realmPoints . data ) {  
      this . currencies . set ( point . name . toLowerCase (), {  
        id:  point . id ,  
        name:  point . name ,  
        emoji:  point . emoji ,  
        isDefault:  point . isDefault  
      });  
    }  
  }  
 
  async  awardCurrency ( memberId ,  currencyName ,  amount ,  reason  =  '' ) {  
    const  currency  =  this . currencies . get ( currencyName . toLowerCase ());  
    if  (! currency ) {  
      throw  new  Error ( `Currency ' ${ currencyName } ' not found` );  
    }  
 
    return  await  this . client . request ( 'PATCH' ,  
      `/realm/ ${ this . client . realmId } /members/ ${ memberId } /point-balance` ,  
      {   
        tokens:  amount ,  
        realmPointId:  currency . id  
      }  
    );  
  }  
 
  async  transferBetweenCurrencies ( memberId ,  fromCurrency ,  toCurrency ,  amount ) {  
    // Convert points between different currencies  
    // This would need custom business logic for exchange rates  
      
    const  exchangeRate  =  this . getExchangeRate ( fromCurrency ,  toCurrency );  
    const  convertedAmount  =  Math . floor ( amount  *  exchangeRate );  
 
    // Deduct from source currency  
    await  this . awardCurrency ( memberId ,  fromCurrency , - amount ,  'Currency conversion' );  
      
    // Add to target currency  
    await  this . awardCurrency ( memberId ,  toCurrency ,  convertedAmount ,  'Currency conversion' );  
      
    return  {  originalAmount:  amount ,  convertedAmount ,  exchangeRate  };  
  }  
 
  getExchangeRate ( fromCurrency ,  toCurrency ) {  
    // Define your exchange rates  
    const  rates  = {  
      'xp_to_coins' :  0.1 ,       // 10 XP = 1 Coin  
      'coins_to_gems' :  0.01 ,    // 100 Coins = 1 Gem  
      'gems_to_coins' :  100 ,     // 1 Gem = 100 Coins  
    };  
 
    const  rateKey  =  ` ${ fromCurrency } _to_ ${ toCurrency } ` ;  
    return  rates [ rateKey ] ||  1 ;  
  }  
}  
 
Batch Point Operations  
Efficiently update multiple members at once: 
async  function  batchPointAward ( client ,  awards ) {  
  // awards = [{ memberId, points, reason }, ...]  
    
  const  updates  =  awards . map ( award  =>  ({  
    memberId:  award . memberId ,  
    tokens:  award . points  
  }));  
 
  try  {  
    const  result  =  await  client . request ( 'PATCH' ,  
      `/realm/ ${ client . realmId } /members/transaction` ,  
      {  updates  }  
    );  
 
    console . log ( `✅ Batch awarded points to  ${ awards . length }  members` );  
    return  result ;  
  }  catch  ( error ) {  
    console . error ( '❌ Batch point award failed:' ,  error . message );  
    throw  error ;  
  }  
}  
 
// Usage examples  
await  batchPointAward ( client , [  
  {  memberId:  'member1' ,  points:  100 ,  reason:  'Event participation'  },  
  {  memberId:  'member2' ,  points:  150 ,  reason:  'Contest winner'  },  
  {  memberId:  'member3' ,  points:  75 ,  reason:  'Helpful member'  }  
]);  
 
Point Transfer Between Members  
Enable peer-to-peer point transfers: 
async  function  transferPoints ( client ,  senderId ,  recipientId ,  amount ,  currency  =  null ) {  
  try  {  
    const  transferData  = {  
      tokens:  amount ,  
      recipientId:  recipientId  
    };  
 
    if  ( currency ) {  
      transferData . realmPointId  =  currency ;  
    }  
 
    const  result  =  await  client . request ( 'PATCH' ,  
      `/realm/ ${ client . realmId } /members/ ${ senderId } /transfer` ,  
      transferData  
    );  
 
    console . log ( `✅ Transferred  ${ amount }  points from  ${ senderId }  to  ${ recipientId } ` );  
    return  result ;  
  }  catch  ( error ) {  
    console . error ( `❌ Transfer failed:  ${ error . message } ` );  
    throw  error ;  
  }  
}  
 
// Usage  
await  transferPoints ( client ,  'sender123' ,  'recipient456' ,  50 );  
 
Gamification Strategies  
Point Earning Systems  
Reward different types of community engagement: const  activityRewards  = {  
  'message_sent' :  5 ,  
  'reaction_added' :  2 ,  
  'voice_joined' :  10 ,  
  'helpful_reaction' :  15 ,  
  'first_message_daily' :  25 ,  
  'streak_7_days' :  100  
};  
 
async  function  rewardActivity ( client ,  memberId ,  activity ) {  
  const  points  =  activityRewards [ activity ];  
  if  ( points ) {  
    await  awardPoints ( client ,  memberId ,  points ,  `Activity:  ${ activity } ` );  
  }  
}  
Reward members for reaching specific milestones: const  milestones  = [  
  {  threshold:  100 ,  reward:  50 ,  title:  'Newcomer'  },  
  {  threshold:  500 ,  reward:  100 ,  title:  'Regular'  },  
  {  threshold:  1000 ,  reward:  200 ,  title:  'Veteran'  },  
  {  threshold:  5000 ,  reward:  500 ,  title:  'Legend'  }  
];  
 
async  function  checkMilestones ( client ,  memberId ,  currentPoints ) {  
  for  ( const  milestone  of  milestones ) {  
    if  ( currentPoints  >=  milestone . threshold ) {  
      // Check if already awarded (you'd track this in your database)  
      const  alreadyAwarded  =  await  hasAwardedMilestone ( memberId ,  milestone . threshold );  
        
      if  (! alreadyAwarded ) {  
        await  awardPoints ( client ,  memberId ,  milestone . reward ,   
          `Milestone achieved:  ${ milestone . title } ` );  
        await  recordMilestoneAwarded ( memberId ,  milestone . threshold );  
      }  
    }  
  }  
}  
Implement daily, weekly, or seasonal bonuses: class  TimeBonusManager  {  
  async  getDailyBonus ( client ,  memberId ) {  
    const  today  =  new  Date (). toDateString ();  
    const  lastClaim  =  await  getLastBonusClaim ( memberId );  
      
    if  ( lastClaim  !==  today ) {  
      const  bonusAmount  =  25 ;  
      await  awardPoints ( client ,  memberId ,  bonusAmount ,  'Daily bonus' );  
      await  recordBonusClaim ( memberId ,  today );  
      return  bonusAmount ;  
    }  
      
    return  0 ;  
  }  
 
  async  getWeeklyBonus ( client ,  memberId ) {  
    const  streak  =  await  getLoginStreak ( memberId );  
    if  ( streak  >=  7 ) {  
      const  bonusAmount  =  100  + ( streak  *  5 );  // Escalating bonus  
      await  awardPoints ( client ,  memberId ,  bonusAmount ,  'Weekly streak bonus' );  
      return  bonusAmount ;  
    }  
      
    return  0 ;  
  }  
}  
 
Leaderboards and Rankings  
Create competitive elements with point-based rankings: 
class  LeaderboardManager  {  
  constructor ( client ) {  
    this . client  =  client ;  
  }  
 
  async  getTopMembers ( limit  =  10 ,  currencyId  =  null ) {  
    const  members  =  await  this . client . searchMembers ( 'drip-id' ,  'all' );  
      
    return  members . data  
      . filter ( member  =>  member . pointBalances  &&  member . pointBalances . length  >  0 )  
      . map ( member  =>  {  
        const  balance  =  currencyId    
          ?  member . pointBalances . find ( b  =>  b . realmPoint . id  ===  currencyId )  
          :  member . pointBalances [ 0 ];  
            
        return  {  
          id:  member . id ,  
          name:  member . displayName  ||  member . username ,  
          points:  balance ?. balance  ||  0 ,  
          currency:  balance ?. realmPoint . name  ||  'Unknown'  
        };  
      })  
      . sort (( a ,  b )  =>  b . points  -  a . points )  
      . slice ( 0 ,  limit )  
      . map (( member ,  index )  =>  ({ ... member ,  rank:  index  +  1  }));  
  }  
 
  async  getMemberRank ( memberId ,  currencyId  =  null ) {  
    const  leaderboard  =  await  this . getTopMembers ( 1000 ,  currencyId );  
    const  memberRank  =  leaderboard . find ( entry  =>  entry . id  ===  memberId );  
      
    return  memberRank  ?  memberRank . rank  :  null ;  
  }  
 
  async  getSeasonalLeaderboard ( season ,  currencyId  =  null ) {  
    // This would require tracking seasonal points separately  
    // Implementation depends on your seasonal point tracking system  
      
    const  seasonalPoints  =  await  this . getSeasonalPoints ( season ,  currencyId );  
    return  seasonalPoints  
      . sort (( a ,  b )  =>  b . points  -  a . points )  
      . map (( entry ,  index )  =>  ({ ... entry ,  rank:  index  +  1  }));  
  }  
}  
 
Point Economy Design  
Balancing Your Economy  
Inflation Control Prevent point inflation by: 
Setting reasonable earning rates 
Creating point sinks (ways to spend points) 
Implementing diminishing returns 
Regular economy reviews 
 
Engagement Optimization Optimize for engagement by: 
Rewarding diverse activities 
Providing clear progression paths 
Balancing effort vs. reward 
Regular feedback and adjustments 
  
Point Sink Strategies  
Create ways for members to spend their points: 
const  pointSinks  = {  
  store_items:  {  
    'premium_role' :  {  cost:  1000 ,  duration:  '30 days'  },  
    'custom_emoji' :  {  cost:  500 ,  permanent:  true  },  
    'channel_access' :  {  cost:  250 ,  duration:  '7 days'  }  
  },  
    
  services:  {  
    'priority_support' :  {  cost:  100 ,  duration:  '24 hours'  },  
    'custom_title' :  {  cost:  300 ,  permanent:  true  },  
    'event_priority' :  {  cost:  150 ,  duration:  'next event'  }  
  },  
    
  gambling:  {  
    'daily_lottery' :  {  cost:  10 ,  chance_to_win:  0.1 ,  payout:  200  },  
    'point_doubler' :  {  cost:  50 ,  chance_to_win:  0.3 ,  payout:  100  }  
  }  
};  
 
Analytics and Monitoring  
Point Flow Tracking  
Monitor how points move through your economy: 
class  PointAnalytics  {  
  constructor ( client ) {  
    this . client  =  client ;  
    this . transactions  = [];  
  }  
 
  recordTransaction ( type ,  memberId ,  amount ,  reason ) {  
    this . transactions . push ({  
      timestamp:  Date . now (),  
      type ,  // 'award', 'deduct', 'transfer'  
      memberId ,  
      amount ,  
      reason  
    });  
  }  
 
  getEconomyStats ( timeframe  =  '7d' ) {  
    const  cutoff  =  Date . now () -  this . getTimeframeMs ( timeframe );  
    const  recentTransactions  =  this . transactions . filter ( t  =>  t . timestamp  >  cutoff );  
 
    return  {  
      totalAwarded:  recentTransactions  
        . filter ( t  =>  t . type  ===  'award' )  
        . reduce (( sum ,  t )  =>  sum  +  t . amount ,  0 ),  
        
      totalDeducted:  recentTransactions  
        . filter ( t  =>  t . type  ===  'deduct' )  
        . reduce (( sum ,  t )  =>  sum  +  Math . abs ( t . amount ),  0 ),  
        
      totalTransfers:  recentTransactions  
        . filter ( t  =>  t . type  ===  'transfer' )  
        . reduce (( sum ,  t )  =>  sum  +  t . amount ,  0 ),  
        
      netPointsCreated:  recentTransactions  
        . reduce (( sum ,  t )  =>  {  
          if  ( t . type  ===  'award' )  return  sum  +  t . amount ;  
          if  ( t . type  ===  'deduct' )  return  sum  -  Math . abs ( t . amount );  
          return  sum ;  // transfers don't create/destroy points  
        },  0 )  
    };  
  }  
 
  getTimeframeMs ( timeframe ) {  
    const  units  = {  
      'd' :  24  *  60  *  60  *  1000 ,  
      'h' :  60  *  60  *  1000 ,  
      'm' :  60  *  1000  
    };  
      
    const  value  =  parseInt ( timeframe );  
    const  unit  =  timeframe . slice (- 1 );  
      
    return  value  * ( units [ unit ] ||  units . d );  
  }  
}  
 
Best Practices  
Keep point values meaningful and consistent: // ✅ Good: Consistent scaling  
const  rewards  = {  
  simple_task:  10 ,  
  medium_task:  25 ,  
  complex_task:  50 ,  
  major_contribution:  100  
};  
 
// ❌ Bad: Inconsistent scaling  
const  badRewards  = {  
  simple_task:  5 ,  
  medium_task:  100 ,  
  complex_task:  15 ,  
  major_contribution:  1000  
};  
Always handle point operations gracefully: async  function  safePointAward ( client ,  memberId ,  points ,  reason ) {  
  try  {  
    // Validate inputs  
    if  (! memberId  ||  typeof  points  !==  'number'  ||  points  ===  0 ) {  
      throw  new  Error ( 'Invalid award parameters' );  
    }  
 
    // Check if member exists  
    const  members  =  await  client . searchMembers ( 'drip-id' ,  memberId );  
    if  (! members . data  ||  members . data . length  ===  0 ) {  
      throw  new  Error ( 'Member not found' );  
    }  
 
    // Award points  
    const  result  =  await  awardPoints ( client ,  memberId ,  points ,  reason );  
      
    // Log successful transaction  
    console . log ( `✅  ${ points }  points awarded to  ${ memberId } :  ${ reason } ` );  
      
    return  result ;  
  }  catch  ( error ) {  
    // Log error  
    console . error ( `❌ Failed to award points:  ${ error . message } ` );  
      
    // Don't throw for non-critical errors  
    return  null ;  
  }  
}  
 
Next Steps  
Building a point economy?  Join our Discord community  to discuss strategies and get feedback from other developers! 💰