### Install Wallets Gem Source: https://context7.com/rameerez/wallets/llms.txt Instructions for adding the gem to a Rails project and running the necessary database migrations. ```ruby gem "wallets" ``` ```bash bundle install rails generate wallets:install rails db:migrate ``` -------------------------------- ### Advanced Wallet Usage Example Source: https://github.com/rameerez/wallets/blob/main/README.md A comprehensive example showing multi-asset management, including top-ups, purchases, and marketplace transfers with metadata. ```ruby class User < ApplicationRecord has_wallets default_asset: :eur end buyer = User.find(1) seller = User.find(2) buyer.wallet(:eur).credit(10_000, category: :top_up, metadata: { source: "card" }) buyer.wallet(:eur).debit(2_500, category: :purchase, metadata: { order_id: 42 }) buyer.wallet(:eur).transfer_to( seller.wallet(:eur), 1_800, category: :marketplace_sale, metadata: { order_id: 42 } ) ``` -------------------------------- ### Install and Configure Wallets Gem Source: https://github.com/rameerez/wallets/blob/main/README.md Steps to integrate the gem into a Rails project, including installation, database migration, and model declaration. ```ruby gem "wallets" ``` ```bash bundle install rails generate wallets:install rails db:migrate ``` ```ruby class User < ApplicationRecord has_wallets default_asset: :coins end ``` -------------------------------- ### Configuring Wallets Gem (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Provides an example of how to configure the Wallets gem in an initializer file. This includes setting the default asset, additional transaction categories, and balance-related thresholds and policies. ```ruby Wallets.configure do |config| config.default_asset = :coins # Useful for app-specific business events like games, marketplaces, or rewards. config.additional_categories = %w[ quest_reward marketplace_sale ride_fare peer_payment ] config.allow_negative_balance = false config.low_balance_threshold = 50 config.transfer_expiration_policy = :preserve end ``` -------------------------------- ### Handle Wallet Exceptions Source: https://context7.com/rameerez/wallets/llms.txt Provides examples of handling specific domain exceptions such as insufficient balance, invalid transfer operations, and argument validation errors during wallet interactions. ```ruby begin wallet.debit(1_000_000, category: :purchase) rescue Wallets::InsufficientBalance => e flash[:error] = "Insufficient balance." end begin user.wallet(:eur).transfer_to(friend.wallet(:usd), 100, category: :gift) rescue Wallets::InvalidTransfer => e # Handle asset mismatch end begin wallet.credit(-50, category: :reward) rescue ArgumentError => e # Handle invalid input end ``` -------------------------------- ### Transfer Expiration Policies (Ruby) Source: https://context7.com/rameerez/wallets/llms.txt Explains how to control expiration dates during credit transfers using three policies: `preserve`, `none`, and `fixed`. It shows examples of each policy and how to apply them. ```ruby sender = user.wallet(:data_mb) receiver = friend.wallet(:data_mb) # Credit expiring data to sender sender.credit(10_240, category: :plan, expires_at: 30.days.from_now) # Policy: preserve (default) - keeps original expiration transfer = sender.transfer_to(receiver, 3_072, category: :gift) transfer.expiration_policy # => "preserve" transfer.inbound_transactions.first.expires_at # => ~30 days from now # Policy: none - creates evergreen (non-expiring) credits transfer = sender.transfer_to( receiver, 1_024, category: :gift, expiration_policy: :none ) transfer.inbound_transactions.first.expires_at # => nil # Policy: fixed - applies a specific expiration date transfer = sender.transfer_to( receiver, 1_024, category: :gift, expiration_policy: :fixed, expires_at: 60.days.from_now ) transfer.inbound_transactions.first.expires_at # => ~60 days from now # Shorthand: passing expires_at implies fixed policy transfer = sender.transfer_to( receiver, 1_024, category: :gift, expires_at: 45.days.from_now ) transfer.expiration_policy # => "fixed" ``` -------------------------------- ### Define User Wallet Association (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Associates a User model with wallet functionality, specifying a default asset for wallet operations. This setup simplifies accessing and managing user wallets. ```ruby class User < ApplicationRecord has_wallets default_asset: :credits end ``` -------------------------------- ### Configuring Wallets Gem (Ruby) Source: https://context7.com/rameerez/wallets/llms.txt Shows how to configure global settings for the Wallets gem within an initializer file. Covers setting the default asset, table prefix, balance policies, thresholds, and custom categories. ```ruby # config/initializers/wallets.rb Wallets.configure do |config| # Default asset for owner.wallet (no argument) config.default_asset = :credits # :coins, :gems, :eur, :data_mb, etc. # Table prefix (set BEFORE first migration) config.table_prefix = "wallets_" # Allow negative balances (for overdrafts/debt) config.allow_negative_balance = false # Threshold for low_balance_reached callback config.low_balance_threshold = 100 # Default transfer expiration policy (:preserve or :none) config.transfer_expiration_policy = :preserve # Custom transaction categories beyond defaults # Defaults: credit, debit, transfer_in, transfer_out, refund, reward, purchase, top_up, adjustment config.additional_categories = %w[ quest_reward marketplace_sale ride_fare peer_payment subscription_renewal ] end ``` -------------------------------- ### Marketplace Balance Management in Ruby on Rails Source: https://context7.com/rameerez/wallets/llms.txt This Ruby on Rails code snippet illustrates a complete marketplace scenario. It shows how buyers can top up their accounts, how orders are paid for by debiting buyers and crediting sellers (minus a platform fee), and how sellers can request payouts. It also includes generating a transaction history for sellers. ```ruby class User < ApplicationRecord has_wallets default_asset: :usd_cents end # Buyer tops up account buyer = User.find(1) buyer.wallet(:usd_cents).credit( 10_000, # $100.00 category: :top_up, metadata: { payment_method: "card", stripe_charge: "ch_xxx" } ) # Process order payment order_total = 5_000 # $50.00 platform_fee = (order_total * 0.10).to_i # 10% fee seller_earnings = order_total - platform_fee seller = User.find(2) ActiveRecord::Base.transaction do # Debit buyer buyer.wallet(:usd_cents).debit( order_total, category: :purchase, metadata: { order_id: order.id } ) # Credit seller (minus fee) seller.wallet(:usd_cents).credit( seller_earnings, category: :marketplace_sale, metadata: { order_id: order.id, gross_amount: order_total, platform_fee: platform_fee, buyer_id: buyer.id } ) end # Seller requests payout payout_amount = seller.wallet(:usd_cents).balance seller.wallet(:usd_cents).debit( payout_amount, category: :payout, metadata: { stripe_transfer_id: "tr_xxx", bank_account: "****1234" } ) # Generate statement seller.wallet(:usd_cents).history.each do |tx| puts "#{tx.created_at.to_date}: #{tx.category.titleize}" puts " Amount: #{tx.amount > 0 ? '+' : ''}#{tx.amount / 100.0} USD" puts " Balance: #{tx.balance_after / 100.0} USD" end ``` -------------------------------- ### Setting Up Lifecycle Callbacks (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Demonstrates how to configure lifecycle callbacks for various wallet events, such as balance changes, transfer completions, low balance notifications, and insufficient balance warnings. These callbacks allow for custom logic execution upon specific events. ```ruby Wallets.configure do |config| config.on_balance_credited do |ctx| Rails.logger.info("Wallet #{ctx.wallet.id} credited by #{ctx.amount}") end config.on_balance_debited do |ctx| Rails.logger.info("Wallet #{ctx.wallet.id} debited by #{ctx.amount}") end config.on_transfer_completed do |ctx| Rails.logger.info("Transfer #{ctx.transfer.id} completed") end config.on_low_balance_reached do |ctx| UserMailer.low_balance(ctx.wallet.owner).deliver_later end config.on_insufficient_balance do |ctx| Rails.logger.warn("Insufficient balance: #{ctx.metadata[:required]}") end end ``` -------------------------------- ### Create Wallets Programmatically Source: https://context7.com/rameerez/wallets/llms.txt Demonstrates how to create wallets for owners using an idempotent method. This ensures that if a wallet already exists for the given owner and asset, the existing record is returned instead of creating a duplicate. ```ruby wallet = Wallets::Wallet.create_for_owner!( owner: user, asset_code: :gems, initial_balance: 500, metadata: { tier: "premium" } ) same_wallet = Wallets::Wallet.create_for_owner!( owner: user, asset_code: "GEMS", initial_balance: 1000 ) ``` -------------------------------- ### Implement Marketplace Seller Balances in Ruby Source: https://github.com/rameerez/wallets/blob/main/README.md Shows how to handle marketplace logic including platform fees, seller payouts, and transaction history auditing using the wallet system. ```ruby class User < ApplicationRecord has_wallets default_asset: :usd_cents end order_total = 5000 platform_fee = (order_total * 0.10).to_i seller_earnings = order_total - platform_fee seller.wallet(:usd_cents).credit( seller_earnings, category: :sale, metadata: { order_id: order.id, gross_amount: order_total, platform_fee: platform_fee, buyer_id: buyer.id } ) seller.wallet(:usd_cents).history.each do |tx| puts "#{tx.created_at}: #{tx.category} #{tx.amount} cents" end ``` -------------------------------- ### Integrate usage_credits and wallets for subscription and transfer logic Source: https://github.com/rameerez/wallets/blob/main/README.md Demonstrates how to define a subscription plan using usage_credits while retaining access to underlying wallet-level transfer methods for peer-to-peer gifting. ```ruby # usage_credits handles ACQUISITION (how users get balance) subscription_plan :basic_data do stripe_price "price_xyz" gives 10_000.credits.every(:month) # 10 GB in MB end # wallet-level movement is still available underneath usage_credits user.credit_wallet.transfer_to(friend.credit_wallet, 3_000) # Gift 3 GB user.credit_wallet.balance # => 7000 MB remaining ``` -------------------------------- ### Run Test Suite (Bash) Source: https://github.com/rameerez/wallets/blob/main/README.md Executes the complete test suite for the project using the 'bundle exec rake test' command. This is the standard way to verify the project's integrity. ```bash bundle exec rake test ``` -------------------------------- ### Performing Credit and Debit Operations (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Illustrates how to credit and debit a wallet with specific amounts and categories. It also shows how to retrieve the current balance, transaction history, and check for sufficient funds. ```ruby wallet = user.wallet(:gems) wallet.credit(100, category: :reward) wallet.debit(20, category: :purchase) wallet.balance wallet.history wallet.has_enough_balance?(50) ``` -------------------------------- ### Build Loyalty Programs with Expiration Logic in Ruby Source: https://github.com/rameerez/wallets/blob/main/README.md Covers the full lifecycle of loyalty points including earning, expiring, transferring, and redeeming rewards. ```ruby class User < ApplicationRecord has_wallets default_asset: :points end # Earn points user.wallet(:points).credit(150, category: :bonus_item, metadata: { sku: "featured_product" }) # Expiring promo user.wallet(:points).credit( 500, category: :welcome_bonus, expires_at: 30.days.from_now ) # Transfer points user.wallet(:points).transfer_to(friend.wallet(:points), 500, category: :gift) # Redeem points user.wallet(:points).debit(2500, category: :redemption, metadata: { reward: "free_coffee" }) ``` -------------------------------- ### Accessing and Checking Wallets (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Demonstrates how to access a user's default wallet, main wallet, specific asset wallets, and check for the existence of a wallet. It also shows how to find a wallet without auto-creating it. ```ruby user.wallet # => default asset wallet user.main_wallet # => same as user.wallet user.wallet(:eur) # => auto-creates the EUR wallet if needed user.wallet?(:gems) # => whether a wallet already exists user.find_wallet(:usd) # => returns nil instead of auto-creating ``` -------------------------------- ### Transferring Value Between Wallets (Ruby) Source: https://context7.com/rameerez/wallets/llms.txt Demonstrates how to move value between wallets of the same asset using the `transfer_to` method. It shows how to initiate a transfer, access transfer details, and handle validation errors. ```ruby buyer = User.find(1) seller = User.find(2) buyer.wallet(:eur).credit(10_000, category: :top_up) # Execute transfer transfer = buyer.wallet(:eur).transfer_to( seller.wallet(:eur), 2_500, category: :marketplace_sale, metadata: { order_id: 42, product: "vintage_lamp" } ) # Transfer details transfer.id # => 1 transfer.amount # => 2500 transfer.asset_code # => "eur" transfer.category # => "marketplace_sale" transfer.expiration_policy # => "preserve" # Access linked transactions transfer.outbound_transaction # => Debit transaction on buyer's wallet transfer.inbound_transactions # => Credit transaction(s) on seller's wallet # Check balances buyer.wallet(:eur).balance # => 7500 seller.wallet(:eur).balance # => 2500 # Transfer validation errors begin buyer.wallet(:eur).transfer_to(seller.wallet(:usd), 100, category: :payment) rescue Wallets::InvalidTransfer => e puts e.message # => "Wallet assets must match" end ``` -------------------------------- ### Manage FIFO Allocation Source: https://context7.com/rameerez/wallets/llms.txt Demonstrates how debits automatically consume the oldest credits first, ensuring correct handling of expiring balances. ```ruby spend = wallet.debit(130, category: :usage) allocations = spend.outgoing_allocations.order(:id) # Allocations track which source transactions were consumed ``` -------------------------------- ### Configure Wallets Gem Callbacks Source: https://context7.com/rameerez/wallets/llms.txt Defines global configuration for the Wallets gem, including setting low balance thresholds and handling various lifecycle events like credits, debits, transfers, and balance depletion using Rails callbacks. ```ruby Wallets.configure do |config| config.low_balance_threshold = 50 config.on_balance_credited do |ctx| Rails.logger.info "[Wallet] #{ctx.owner.class}##{ctx.owner.id} credited #{ctx.amount}" Analytics.track("wallet_credited", { user_id: ctx.owner.id, amount: ctx.amount, category: ctx.category, new_balance: ctx.new_balance }) end config.on_balance_debited do |ctx| Rails.logger.info "[Wallet] #{ctx.owner.class}##{ctx.owner.id} debited #{ctx.amount}" end config.on_transfer_completed do |ctx| TransferMailer.confirmation(ctx.transfer).deliver_later end config.on_low_balance_reached do |ctx| LowBalanceNotificationJob.perform_later( user_id: ctx.owner.id, balance: ctx.new_balance, threshold: ctx.threshold ) end config.on_balance_depleted do |ctx| Rails.logger.warn "[Wallet] #{ctx.owner.class}##{ctx.owner.id} balance depleted" end config.on_insufficient_balance do |ctx| Rails.logger.warn "[Wallet] Insufficient: needed #{ctx.metadata[:required]}, had #{ctx.metadata[:available]}" InsufficientBalanceMailer.notify(ctx.owner, ctx.metadata[:required]).deliver_later end end ``` -------------------------------- ### Setting Expiring Balances (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Illustrates how to credit a wallet with an expiration date, ensuring that the balance is automatically managed and debits are allocated against the oldest available credits first. ```ruby user.wallet(:coins).credit( 1_000, category: :season_reward, expires_at: 30.days.from_now ) ``` -------------------------------- ### Manage Wallet Balances and Transfers in Ruby Source: https://github.com/rameerez/wallets/blob/main/README.md Demonstrates how to credit, debit, and transfer assets between user wallets. It highlights the use of categories and metadata for audit trails and handling expirable balances. ```ruby user.wallet(:mb).credit(10_240, expires_at: month_end) user.wallet(:minutes).credit(500, expires_at: month_end) # Transfer balance user.wallet(:mb).transfer_to(friend.wallet(:mb), 3_072) # Debit balance user.wallet(:mb).debit(512, category: :network_usage) puts user.wallet(:mb).balance ``` -------------------------------- ### Manage Seasonal and Peer-to-Peer Transactions in Ruby Source: https://github.com/rameerez/wallets/blob/main/README.md Demonstrates how to credit expiring currency for seasonal events and perform secure peer-to-peer transfers between wallet instances. ```ruby player.wallet(:snowflakes).credit( 1_000, category: :event_reward, expires_at: Date.new(2024, 1, 7) ) player.wallet(:gold).transfer_to( other_player.wallet(:gold), 100, category: :trade, metadata: { item_received: "rare_armor" } ) ``` -------------------------------- ### Run Specific Appraisal Test (Bash) Source: https://github.com/rameerez/wallets/blob/main/README.md Executes the test suite for a specific appraisal, such as 'rails-7.2' or 'rails-8.1'. This is useful for testing compatibility with different Rails versions. ```bash bundle exec appraisal rails-7.2 rake test ``` ```bash bundle exec appraisal rails-8.1 rake test ``` -------------------------------- ### Manage Expiring Balances Source: https://context7.com/rameerez/wallets/llms.txt Shows how to apply expiration dates to credit transactions. Expired credits are automatically excluded from balance calculations and skipped during FIFO debit operations. ```ruby wallet = user.wallet(:promo_credits) wallet.credit(100, category: :welcome_bonus, expires_at: 7.days.from_now) wallet.credit(200, category: :loyalty_reward, expires_at: 30.days.from_now) wallet.credit(50, category: :permanent_bonus) wallet.transactions.not_expired.count wallet.transactions.expired.count ``` -------------------------------- ### Configure ActiveRecord Models with has_wallets Source: https://context7.com/rameerez/wallets/llms.txt Enables wallet functionality on an ActiveRecord model. Supports default assets, auto-creation, and initial balances. ```ruby class User < ApplicationRecord has_wallets default_asset: :credits end class Player < ApplicationRecord has_wallets default_asset: :gold, auto_create: true, initial_balance: 100 end ``` -------------------------------- ### Partial Redemption with Points and Cash Source: https://github.com/rameerez/wallets/blob/main/README.md Demonstrates how to debit a portion of points and charge the remainder via cash for a partial redemption. This is useful for loyalty programs where users can redeem rewards using a combination of points and cash. ```ruby points_portion = 500 user.wallet(:points).debit( points_portion, category: :partial_redemption, metadata: { order_id: order.id, points_value_cents: points_portion } ) ``` -------------------------------- ### Manage multi-asset game economy with wallets Source: https://github.com/rameerez/wallets/blob/main/README.md Illustrates how to handle multiple resource types like wood, stone, gold, and gems within a single player model using the wallets gem. ```ruby class Player < ApplicationRecord has_wallets default_asset: :gold end # Quest rewards multiple resources player.wallet(:wood).credit(100, category: :quest_reward, metadata: { quest: "forest_patrol" }) player.wallet(:stone).credit(50, category: :quest_reward) player.wallet(:gold).credit(25, category: :quest_reward) # Crafting consumes resources player.wallet(:wood).debit(30, category: :crafting, metadata: { item: "wooden_sword" }) # Premium currency from in-app purchase player.wallet(:gems).credit(500, category: :purchase, metadata: { sku: "gem_pack_500" }) ``` -------------------------------- ### Configuring Transfer Expiration Policies (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Demonstrates how to override the default transfer expiration behavior. Options include preserving original expirations, making transfers evergreen, or setting a fixed expiration date. ```ruby sender.transfer_to(receiver, 100, expiration_policy: :none) # evergreen on receive sender.transfer_to(receiver, 100, expires_at: 30.days.from_now) # fixed expiration on receive sender.transfer_to(receiver, 100, expiration_policy: :fixed, expires_at: 30.days.from_now) ``` -------------------------------- ### Implement telecom data management with wallets Source: https://github.com/rameerez/wallets/blob/main/README.md Shows how to manage passive data consumption and user-to-user data transfers using the wallets gem, emphasizing the use of integers for precision. ```ruby class User < ApplicationRecord has_wallets default_asset: :data_mb # Store in MB for precision end # Monthly plan grants 10 GB (stored as 10,240 MB) user.wallet(:data_mb).credit( 10_240, category: :monthly_plan, expires_at: 1.month.from_now, metadata: { plan: "basic", period: "2024-03" } ) # Network usage consumes data passively user.wallet(:data_mb).debit(512, category: :network_usage) # User transfers 3 GB to a friend user.wallet(:data_mb).transfer_to( friend.wallet(:data_mb), 3_072, category: :gift, metadata: { message: "Here's some extra data!" } ) user.wallet(:data_mb).balance # => 6656 MB (6.5 GB remaining) ``` -------------------------------- ### Gig Economy Driver Earnings and Payouts Source: https://github.com/rameerez/wallets/blob/main/README.md Illustrates how to manage driver earnings in a gig economy app. It covers crediting for ride fares and tips, and then debiting the total balance for a weekly payout. This pattern is suitable for platforms like Uber or DoorDash. ```ruby class Driver < ApplicationRecord has_wallets default_asset: :usd_cents end # Ride completed driver.wallet(:usd_cents).credit( 1250, # $12.50 base fare category: :ride_fare, metadata: { ride_id: ride.id, distance_miles: 5.2 } ) # Tip added later driver.wallet(:usd_cents).credit( 300, # $3.00 tip category: :tip, metadata: { ride_id: ride.id, rider_id: rider.id } ) # Weekly payout driver.wallet(:usd_cents).debit( driver.wallet(:usd_cents).balance, category: :weekly_payout, metadata: { payout_date: Date.current, bank_account: "****1234" } ) ``` -------------------------------- ### Debit Wallets and Handle Insufficient Balance Source: https://context7.com/rameerez/wallets/llms.txt Deducts value from a wallet using FIFO logic. Includes error handling for insufficient funds and balance checking. ```ruby begin wallet.debit(10_000, category: :purchase) rescue Wallets::InsufficientBalance => e puts "Not enough balance: #{e.message}" end ``` -------------------------------- ### Adding Metadata to Transactions (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Shows how to include custom metadata with credit transactions, allowing for richer tracking of transaction details such as the source campaign or specific IDs. ```ruby wallet.credit( 500, category: :top_up, metadata: { source: "promo_campaign", campaign_id: 12 } ) ``` -------------------------------- ### Credit Wallets with Transactions Source: https://context7.com/rameerez/wallets/llms.txt Adds positive integer amounts to a wallet. Supports metadata and optional expiration dates for credits. ```ruby transaction = wallet.credit( 500, category: :top_up, metadata: { source: "promo_campaign", campaign_id: 42 }, expires_at: 30.days.from_now ) ``` -------------------------------- ### Querying Transaction History (Ruby) Source: https://context7.com/rameerez/wallets/llms.txt Details how to access and filter transaction history using built-in scopes. It covers retrieving all transactions, filtering by type, date, category, and status, and accessing transaction properties. ```ruby wallet = user.wallet(:coins) # Get all transactions chronologically wallet.history # => ActiveRecord::Relation ordered by created_at ASC # Use built-in scopes Wallets::Transaction.credits # => All positive transactions Wallets::Transaction.debits # => All negative transactions Wallets::Transaction.recent # => Ordered by created_at DESC Wallets::Transaction.by_category(:reward) # => Filter by category Wallets::Transaction.not_expired # => Non-expired credits Wallets::Transaction.expired # => Expired credits # Chain scopes on wallet transactions wallet.transactions.credits.recent.limit(10) wallet.transactions.by_category(:purchase).sum(:amount) # Transaction properties tx = wallet.transactions.last tx.credit? # => true/false tx.debit? # => true/false tx.expired? # => true/false tx.remaining_amount # => Unallocated amount (for credits) tx.allocated_amount # => Amount already allocated to debits tx.balance_before # => Balance snapshot before this transaction tx.balance_after # => Balance snapshot after this transaction tx.owner # => The wallet owner (User, Player, etc.) ``` -------------------------------- ### Performing Wallet Transfers (Ruby) Source: https://github.com/rameerez/wallets/blob/main/README.md Details how to transfer funds between two user wallets. Transfers require both wallets to be of the same asset type and class. It also shows how to access transaction details related to the transfer. ```ruby sender = user.wallet(:eur) receiver = other_user.wallet(:eur) transfer = sender.transfer_to( receiver, 2_000, category: :peer_payment, metadata: { message: "Dinner split" } ) transfer.outbound_transaction transfer.inbound_transactions ``` -------------------------------- ### HTML Structure for Error Page Source: https://github.com/rameerez/wallets/blob/main/test/dummy/public/500.html This HTML snippet defines the basic structure of the error page, including meta tags, font size, and body styling. It sets up the layout for displaying the error message. ```html Error

We’re sorry, but something went wrong (500 Internal Server Error)

If you’re the application owner check the logs for more information.

``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.