Skip to content

Commit

Permalink
[PAY-2060] Fix wrong challenge claimed so far amounts (#6398)
Browse files Browse the repository at this point in the history
  • Loading branch information
dharit-tan authored Oct 19, 2023
1 parent 75d0866 commit 785a815
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 23 deletions.
1 change: 1 addition & 0 deletions packages/common/src/models/AudioRewards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export type UserChallenge = {
specifier: Specifier
user_id: string
amount: number
disbursed_amount: number
}

export type Specifier = string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ type UserChallengesResponse = [
max_steps: number
challenge_type: string
amount: string
disbursed_amount: number
metadata: object
}
]
Expand Down
10 changes: 9 additions & 1 deletion packages/common/src/utils/challenges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ export const isAudioMatchingChallenge = (
)
}

// TODO: currently only $AUDIO matching challenges have cooldown
// so this works, but really we should check if `cooldown_period` exists on the
// challenge instead of using `!isAudioMatchingChallenge`. PAY-2030
export const isCooldownChallengeClaimable = (
challenge: UndisbursedUserChallenge
) => dayjs.utc().diff(dayjs.utc(challenge.created_at), 'day') >= 7
) => {
return (
!isAudioMatchingChallenge(challenge.challenge_id) ||
dayjs.utc().diff(dayjs.utc(challenge.created_at), 'day') >= 7
)
}
3 changes: 2 additions & 1 deletion packages/discovery-provider/src/api/v1/models/users.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from flask_restx import fields

from .common import ns, StringEnumToLower
from .common import StringEnumToLower, ns
from .playlist_library import playlist_library

# DEPRECATED
Expand Down Expand Up @@ -120,6 +120,7 @@
"max_steps": fields.Integer(),
"challenge_type": fields.String(required=True),
"amount": fields.String(required=True),
"disbursed_amount": fields.Integer(required=True),
"metadata": fields.Raw(required=True),
},
)
Expand Down
44 changes: 36 additions & 8 deletions packages/discovery-provider/src/queries/get_challenges.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from src.models.rewards.challenge import Challenge, ChallengeType
from src.models.rewards.challenge_disbursement import ChallengeDisbursement
from src.models.rewards.user_challenge import UserChallenge
from src.utils.spl_audio import from_lamports


class ChallengeResponse(TypedDict):
Expand All @@ -22,11 +23,29 @@ class ChallengeResponse(TypedDict):
max_steps: Optional[int]
challenge_type: str
amount: str
disbursed_amount: int
metadata: Dict


def get_disbursements_by_challenge_id(
disbursements: List[ChallengeDisbursement], challenge_id: str
) -> List[ChallengeDisbursement]:
return list(filter(lambda d: d.challenge_id == challenge_id, disbursements))


def get_disbursed_amount(disbursements: List[ChallengeDisbursement]) -> int:
if disbursements is None:
return 0
return sum(
from_lamports(disbursement.amount)
for disbursement in filter(lambda x: x is not None, disbursements)
)


def rollup_aggregates(
user_challenges: List[UserChallenge], parent_challenge: Challenge
user_challenges: List[UserChallenge],
parent_challenge: Challenge,
disbursements: List[ChallengeDisbursement],
) -> ChallengeResponse:
num_complete = reduce(
lambda acc, cur: cast(int, acc) + cur.amount if cur.is_complete else acc,
Expand All @@ -52,6 +71,7 @@ def rollup_aggregates(
"is_active": parent_challenge.active,
"is_disbursed": False, # This doesn't indicate anything for aggregate challenges
"amount": parent_challenge.amount,
"disbursed_amount": get_disbursed_amount(disbursements),
"metadata": {},
}
return response_dict
Expand All @@ -60,7 +80,7 @@ def rollup_aggregates(
def to_challenge_response(
user_challenge: UserChallenge,
challenge: Challenge,
disbursement: ChallengeDisbursement,
disbursements: List[ChallengeDisbursement],
metadata: Dict,
) -> ChallengeResponse:
return {
Expand All @@ -72,8 +92,9 @@ def to_challenge_response(
"max_steps": challenge.step_count,
"challenge_type": challenge.type,
"is_active": challenge.active,
"is_disbursed": disbursement is not None,
"is_disbursed": disbursements is not None and len(disbursements) > 0,
"amount": challenge.amount,
"disbursed_amount": get_disbursed_amount(disbursements),
"metadata": metadata,
}

Expand All @@ -94,6 +115,7 @@ def create_empty_user_challenges(
"is_active": challenge.active,
"is_disbursed": False,
"amount": challenge.amount,
"disbursed_amount": 0,
"metadata": metadatas[i],
}
user_challenges.append(user_challenge)
Expand Down Expand Up @@ -170,9 +192,8 @@ def get_challenges(
if show_historical or all_challenges_map[i[0].challenge_id].active
]
disbursements: List[ChallengeDisbursement] = [
i[1] for i in challenges_and_disbursements
i[1] for i in challenges_and_disbursements if i[1] is not None
]

regular_user_challenges: List[ChallengeResponse] = []
aggregate_user_challenges_map: DefaultDict[str, List[UserChallenge]] = defaultdict(
lambda: []
Expand All @@ -197,11 +218,12 @@ def get_challenges(
and not user_challenge.is_complete
):
continue

user_challenge_dict = to_challenge_response(
user_challenge,
parent_challenge,
disbursements[i],
get_disbursements_by_challenge_id(
disbursements, user_challenge.challenge_id
),
existing_metadata[i],
)
override_step_count = event_bus.get_manager(
Expand All @@ -214,7 +236,13 @@ def get_challenges(
rolled_up: List[ChallengeResponse] = []
for challenge_id, challenges in aggregate_user_challenges_map.items():
parent_challenge = all_challenges_map[challenge_id]
rolled_up.append(rollup_aggregates(challenges, parent_challenge))
rolled_up.append(
rollup_aggregates(
challenges,
parent_challenge,
get_disbursements_by_challenge_id(disbursements, challenge_id),
)
)

# Return empty user challenges for active challenges that are non-hidden
# and visible for the current user
Expand Down
6 changes: 6 additions & 0 deletions packages/discovery-provider/src/utils/spl_audio.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@
SPL_TO_WEI = 10**10
SPL_TO_WEI_PADDING = "0" * 10

LAMPORTS_PER_SOL = 10**8


def to_wei(balance: Union[int, str]):
return int(balance) * SPL_TO_WEI if balance else 0


def to_wei_string(spl_amount: Union[int, str]):
return f"{spl_amount}{SPL_TO_WEI_PADDING}"


def from_lamports(spl_amount: str):
return int(spl_amount) / LAMPORTS_PER_SOL if spl_amount else 0
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ type DiscoveryNodeChallenge = {
wallet: string
completed_blocknumber: number
created_at: string
disbursed_amount: number
}

export type DiscoveryRelayBody = {
Expand Down
15 changes: 10 additions & 5 deletions packages/web/src/common/store/pages/audio-rewards/store.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,8 @@ describe('Rewards Page Sagas', () => {
max_steps: 7,
challenge_type: 'numeric',
specifier: '1',
user_id: '1'
user_id: '1',
disbursed_amount: 7
},
{
challenge_id: 'referrals',
Expand All @@ -487,7 +488,8 @@ describe('Rewards Page Sagas', () => {
max_steps: 5,
challenge_type: 'numeric',
specifier: '1',
user_id: '1'
user_id: '1',
disbursed_amount: 5
},
{
challenge_id: 'track-upload',
Expand All @@ -499,7 +501,8 @@ describe('Rewards Page Sagas', () => {
max_steps: 3,
challenge_type: 'numeric',
specifier: '1',
user_id: '1'
user_id: '1',
disbursed_amount: 3
}
]
const fetchUserChallengesProvisions: StaticProvider[] = [
Expand Down Expand Up @@ -607,7 +610,8 @@ describe('Rewards Page Sagas', () => {
max_steps: 7,
challenge_type: 'numeric',
specifier: '1',
user_id: '1'
user_id: '1',
disbursed_amount: 7
}
]

Expand Down Expand Up @@ -659,7 +663,8 @@ describe('Rewards Page Sagas', () => {
max_steps: 7,
challenge_type: 'numeric',
specifier: '1',
user_id: '1'
user_id: '1',
disbursed_amount: 2
}
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
OptimisticUserChallenge,
challengeRewardsConfig,
formatNumberCommas,
useAudioMatchingChallengeCooldownSchedule
useAudioMatchingChallengeCooldownSchedule,
challengesSelectors
} from '@audius/common'
import { IconArrowRight, IconCloudUpload, Text } from '@audius/harmony'
import {
Expand All @@ -16,6 +17,7 @@ import {
import cn from 'classnames'
import dayjs from 'dayjs'
import utc from 'dayjs/plugin/utc'
import { useSelector } from 'react-redux'

import LoadingSpinner from 'components/loading-spinner/LoadingSpinner'
import { SummaryTable } from 'components/summary-table'
Expand All @@ -28,6 +30,8 @@ import { ProgressDescription } from './ProgressDescription'
import { ProgressReward } from './ProgressReward'
import styles from './styles.module.css'

const { getOptimisticUserChallenges } = challengesSelectors

dayjs.extend(utc)

const messages = {
Expand Down Expand Up @@ -97,11 +101,7 @@ export const AudioMatchingRewardsModalContent = ({
const { fullDescription } = challengeRewardsConfig[challengeName]
const { cooldownChallenges, claimableAmount, cooldownChallengesSummary } =
useAudioMatchingChallengeCooldownSchedule(challenge?.challenge_id)

const audioClaimedSoFar = challenge
? challenge.amount * challenge.current_step_count -
challenge.claimableAmount
: 0
const userChallenge = useSelector(getOptimisticUserChallenges)[challengeName]

const progressDescription = (
<ProgressDescription
Expand All @@ -123,11 +123,11 @@ export const AudioMatchingRewardsModalContent = ({
)

const progressStatusLabel =
audioClaimedSoFar > 0 ? (
userChallenge && userChallenge?.disbursed_amount > 0 ? (
<div className={styles.audioMatchingTotalContainer}>
<Text variant='label' size='l' strength='strong' color='subdued'>
{messages.totalEarned(
formatNumberCommas(audioClaimedSoFar.toString())
formatNumberCommas(userChallenge.disbursed_amount.toString())
)}
</Text>
</div>
Expand Down

0 comments on commit 785a815

Please sign in to comment.