Reward Engine
The reward engine is implemented as a pure domain package:
packages/reward-engine/src/evaluate.ts
No database or network side effects exist in this package.
Core Functions
evaluateReward(input)
Computes points earned for a transaction.
Input includes:
amountMinorUnitsrule(conversionRate, thresholds, caps, rounding)campaignMultiplier
Decision flow:
- enforce minimum spend (
minSpendMinorUnits) - compute base points from dollars (
amountMinorUnits / 100) - apply multiplier
- apply per-transaction cap (
maxPointsPerTransaction) - apply rounding policy (
floor|ceil|round)
Output:
{
pointsEarned: number,
appliedRule: RuleConfig,
didMeetMinSpend: boolean
}
checkRedemptionEligibility(balance, cartAmountMinorUnits, rule)
Determines whether redemption is allowed and max redeemable points.
Rules applied:
- block when balance below
minBalanceToRedeem - cap redemption by cart percentage (
maxRedemptionPercentage) - cap by current balance
Rule Config Contract
Rule config schema comes from packages/types/src/reward.ts.
Fields:
conversionRateminSpendMinorUnitsmaxPointsPerTransactionminBalanceToRedeemmaxRedemptionPercentageroundingPolicy
Runtime Integration
Engine is used in API ingestion path:
apps/api/src/services/ingestion.ts-> reward calculation for POS transactions
When points > 0, wallet credit path is executed via wallet service.
Determinism and Auditability
The pure-function design gives:
- repeatable outcomes for same inputs,
- easy unit testing,
- easier dispute resolution using historical transaction + rule snapshots.
Existing Automated Coverage
packages/reward-engine/src/evaluate.test.ts verifies:
- min-spend block,
- basic conversion,
- multiplier and cap,
- rounding behavior,
- redemption eligibility and caps,
- deterministic behavior.
Related Docs
Written byDhruv Doshi