The GenLayer Points platform uses a relational database schema built with Django ORM. The data model is organized around users, contributions, leaderboards, and category-specific profiles.
Points are calculated once at contribution creation and never change, even if multipliers are updated later. This ensures fairness and prevents retroactive changes.
# Examplecontribution = Contribution.objects.create( user=user, contribution_type=type, points=100, # Base points multiplier_at_creation=1.5, # Active multiplier at creation time frozen_global_points=150 # 100 × 1.5 = 150 (LOCKED))
# Own contributionsown_points = Contribution.objects.filter( user=user, contribution_type__category__slug='validator').exclude( contribution_type__slug='validator' # Exclude graduation badge).aggregate(Sum('frozen_global_points'))['frozen_global_points__sum']# Referral points (10% of referred users' points)referral_points = user.referral_points.builder_points + user.referral_points.validator_pointstotal_points = own_points + referral_points
Frozen at graduation time - never recalculated:
# Points are locked when user gets 'validator' contributiongrad_contrib = Contribution.objects.filter( user=user, contribution_type__slug='validator').first()# All contributions and referrals up to graduation_date are frozenfrozen_points = calculate_points_at_date(grad_contrib.contribution_date)
Location: leaderboard/models.pyTracks 10% bonus from referred users:
class ReferralPoints(BaseModel): user = OneToOneField(User, on_delete=CASCADE) builder_points = PositiveIntegerField(default=0) # 10% of referred builders validator_points = PositiveIntegerField(default=0) # 10% of referred validators
Calculation:
# Get all users referred by this userreferred_users = User.objects.filter(referred_by=referrer)# Calculate 10% of their builder contributionsbuilder_points = int(Contribution.objects.filter( user__in=referred_users, contribution_type__category__slug='builder').aggregate(Sum('frozen_global_points'))['frozen_global_points__sum'] * 0.1)# Calculate 10% of their validator contributionsvalidator_points = int(Contribution.objects.filter( user__in=referred_users, contribution_type__category__slug='validator').aggregate(Sum('frozen_global_points'))['frozen_global_points__sum'] * 0.1)
-- UsersCREATE INDEX idx_users_address ON users_user(address);CREATE INDEX idx_users_referral_code ON users_user(referral_code);CREATE INDEX idx_users_visible ON users_user(visible);-- ContributionsCREATE INDEX idx_contributions_user ON contributions_contribution(user_id);CREATE INDEX idx_contributions_type ON contributions_contribution(contribution_type_id);CREATE INDEX idx_contributions_date ON contributions_contribution(contribution_date);CREATE INDEX idx_contributions_points ON contributions_contribution(frozen_global_points);-- Submitted ContributionsCREATE INDEX idx_submitted_state ON contributions_submittedcontribution(state);CREATE INDEX idx_submitted_assigned ON contributions_submittedcontribution(assigned_to_id);CREATE INDEX idx_submitted_user ON contributions_submittedcontribution(user_id);-- LeaderboardCREATE INDEX idx_leaderboard_type ON leaderboard_leaderboardentry(type);CREATE INDEX idx_leaderboard_rank ON leaderboard_leaderboardentry(rank);CREATE INDEX idx_leaderboard_points ON leaderboard_leaderboardentry(total_points);-- MultipliersCREATE INDEX idx_multipliers_valid_from ON leaderboard_globalleaderboardmultiplier(valid_from);CREATE INDEX idx_multipliers_type ON leaderboard_globalleaderboardmultiplier(contribution_type_id);
# Add a new field with defaultoperations = [ migrations.AddField( model_name='user', name='new_field', field=models.CharField(max_length=100, default=''), ),]
# Rename without data lossoperations = [ migrations.RenameField( model_name='contribution', old_name='old_name', new_name='new_name', ),]
# Custom data transformationdef forwards_func(apps, schema_editor): User = apps.get_model('users', 'User') for user in User.objects.all(): # Transform data user.save()operations = [ migrations.RunPython(forwards_func),]