⚠ This page is served via a proxy. Original site: https://github.com
This service does not collect credentials or authentication data.
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/common/src/store/ui/modals/parentSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import {

export const initialState: BasicModalsState = {
TiersExplainer: { isOpen: false },
TrendingRewardsExplainer: { isOpen: false },
ChallengeRewards: { isOpen: false },
ClaimAllRewards: { isOpen: false },
ClaimVestedCoinsModal: { isOpen: false },
Expand All @@ -25,6 +24,7 @@ export const initialState: BasicModalsState = {
FeedFilter: { isOpen: false },
PurchaseVendor: { isOpen: false },
TrendingGenreSelection: { isOpen: false },
TrendingRewardsExplainer: { isOpen: false },
SocialProof: { isOpen: false },
EditFolder: { isOpen: false },
EditTrack: { isOpen: false },
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/store/ui/modals/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ export type CreateChatModalState = {

export type Modals =
| 'TiersExplainer'
| 'TrendingRewardsExplainer'
| 'ChallengeRewards'
| 'ClaimAllRewards'
| 'ClaimVestedCoinsModal'
Expand All @@ -59,6 +58,7 @@ export type Modals =
| 'FeedFilter'
| 'PurchaseVendor'
| 'TrendingGenreSelection'
| 'TrendingRewardsExplainer'
| 'SocialProof'
| 'EditFolder'
| 'EditTrack'
Expand Down
104 changes: 70 additions & 34 deletions packages/common/src/utils/challenges.ts
Original file line number Diff line number Diff line change
Expand Up @@ -183,29 +183,23 @@ export const challengeRewardsConfig: Partial<
progressLabel: 'No Recent Activity',
panelButtonText: 'View Details'
},
'trending-playlist': {
id: 'trending-playlist',
title: 'Trending Playlists Weekly Top 5',
[ChallengeName.TrendingTrack]: {
id: ChallengeName.TrendingTrack,
title: 'Global Trending Weekly Top 5',
description: () => 'Top 5 winners are selected every Friday at Noon PT!',
panelButtonText: 'See More'
},
tp: {
id: 'trending-playlist',
[ChallengeName.TrendingPlaylist]: {
id: ChallengeName.TrendingPlaylist,
title: 'Trending Playlists Weekly Top 5',
description: () => 'Top 5 winners are selected every Friday at Noon PT!',
panelButtonText: 'See More'
},
'trending-track': {
title: 'Global Trending Weekly Top 5',
description: () => 'Top 5 winners are selected every Friday at Noon PT!',
panelButtonText: 'See More',
id: 'trending-track'
},
tt: {
title: 'Global Trending Weekly Top 5',
[ChallengeName.TrendingUndergroundTrack]: {
id: ChallengeName.TrendingUndergroundTrack,
title: 'Underground Trending Weekly Top 5',
description: () => 'Top 5 winners are selected every Friday at Noon PT!',
panelButtonText: 'See More',
id: 'trending-track'
panelButtonText: 'See More'
},
'top-api': {
title: 'API Apps: Monthly Top 10 ',
Expand All @@ -220,18 +214,6 @@ export const challengeRewardsConfig: Partial<
panelButtonText: 'More Info',
id: 'verified-upload'
},
'trending-underground': {
title: 'Underground Trending Weekly Top 5',
description: () => 'Top 5 winners are selected every Friday at Noon PT!',
panelButtonText: 'See More',
id: 'trending-underground'
},
tut: {
title: 'Underground Trending Weekly Top 5',
description: () => 'Top 5 winners are selected every Friday at Noon PT!',
panelButtonText: 'See More',
id: 'trending-underground'
},
[ChallengeName.OneShot]: {
shortTitle: 'Airdrop 2: Artists',
title: 'Airdrop 2: Artist Appreciation',
Expand Down Expand Up @@ -281,9 +263,9 @@ export const challengeRewardsConfig: Partial<
id: ChallengeName.PlayCount1000,
title: '1,000 Plays',
description: () =>
`Hit 1,000 plays across all of your tracks to earn an $AUDIO Reward (requires verification).`,
`Hit 1,000 plays across all of your tracks to earn an $AUDIO Reward`,
fullDescription: () =>
`Hit 1,000 plays across all of your tracks to earn an $AUDIO Reward (requires verification).`,
`Hit 1,000 plays across all of your tracks to earn an $AUDIO Reward`,
progressLabel: '%0 Plays',
remainingLabel: '%0 Plays',
panelButtonText: 'More Info'
Expand All @@ -292,9 +274,9 @@ export const challengeRewardsConfig: Partial<
id: ChallengeName.PlayCount10000,
title: '10,000 Plays',
description: () =>
`Hit 10,000 plays across all of your tracks to earn an $AUDIO Reward (requires verification).`,
`Hit 10,000 plays across all of your tracks to earn an $AUDIO Reward`,
fullDescription: () =>
`Hit 10,000 plays across all of your tracks to earn an $AUDIO Reward (requires verification).`,
`Hit 10,000 plays across all of your tracks to earn an $AUDIO Reward`,
progressLabel: '%0 Plays',
remainingLabel: '%0 Plays',
panelButtonText: 'More Info'
Expand Down Expand Up @@ -364,7 +346,7 @@ export const makeOptimisticChallengeSortComparator = (
return 0
}

// Priority 1: Claimable challenges come first
// Priority 1: Claimable challenges (Ready to Claim) come first
if (
userChallenge1.claimableAmount > 0 &&
userChallenge2.claimableAmount <= 0
Expand All @@ -378,7 +360,41 @@ export const makeOptimisticChallengeSortComparator = (
return 1
}

// Priority 2: New and not disbursed challenges come next
// Priority 2: Reward Pending challenges come next
// Reward Pending = completed with cooldown, or has undisbursed specifiers with cooldown
const isRewardPending = (challenge: OptimisticUserChallenge) => {
// Completed with cooldown days
if (
challenge.state === 'completed' &&
challenge.cooldown_days &&
challenge.cooldown_days > 0 &&
challenge.claimableAmount <= 0
) {
return true
}
// Has undisbursed specifiers with cooldown (for Cosign, RemixContestWinner, etc.)
if (
challenge.undisbursedSpecifiers &&
challenge.undisbursedSpecifiers.length > 0 &&
challenge.cooldown_days &&
challenge.cooldown_days > 0 &&
challenge.claimableAmount <= 0
) {
return true
}
return false
}

const isPending1 = isRewardPending(userChallenge1)
const isPending2 = isRewardPending(userChallenge2)
if (isPending1 && !isPending2) {
return -1
}
if (isPending2 && !isPending1) {
return 1
}

// Priority 3: New and not disbursed challenges come next
const isNewAndNotDisbursed = (userChallenge: OptimisticUserChallenge) =>
isNewChallenge(userChallenge.challenge_id) &&
userChallenge.state !== 'disbursed'
Expand All @@ -392,7 +408,7 @@ export const makeOptimisticChallengeSortComparator = (
return 1
}

// Priority 3: Non-disbursed come before disbursed
// Priority 4: Non-disbursed come before disbursed
if (
userChallenge1.state !== 'disbursed' &&
userChallenge2.state === 'disbursed'
Expand Down Expand Up @@ -576,3 +592,23 @@ export const getChallengeStatusLabel = (
return DEFAULT_STATUS_LABELS.AVAILABLE
}
}

/**
* Determines if a reward is open to all users or requires verification
* @param rewardId The reward ID to check
* @returns true if the reward is open to all users, false if it requires verification
*/
export const isRewardOpenToAll = (rewardId: ChallengeRewardID): boolean => {
const openToAllRewards = new Set<ChallengeRewardID>([
ChallengeName.Tastemaker,
ChallengeName.TrendingPlaylist,
ChallengeName.TrendingTrack,
ChallengeName.TrendingUndergroundTrack,
ChallengeName.AudioMatchingBuy,
ChallengeName.Referred,
ChallengeName.RemixContestWinner,
ChallengeName.Cosign
])

return openToAllRewards.has(rewardId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,32 @@ if (!AAO_AUTH_PASSWORD) {
}

const rewardAmountRatio = 10
const skipValidationChallenges = ['dvl']
const openRewards = [
'dvl', // daily volume rewards
't', // tastemaker
'tp', // trending playlists
'tt', // trending
'tut', // trending underground
'b', // audio match buy (from verified user)
'rd', // referred (by verified user)
'w', // remix contest winner (from verified user)
'cs', // cosign (from verified user)
]

const verifiedRewards = [
'u', // uploads
's', // audio match sell
'r', // referral
'c', // first comment
'cp', // comment pin
'e', // listen streak
'fp', // first playlist
'm', // mobile install
'p', // profile completion
'p1', // 250 plays
'p2', // 1000 plays
'p3', // 10000 plays
]

const sdk = getAudiusSdk()

Expand Down Expand Up @@ -174,27 +199,21 @@ app.post('/attestation/:handle', async (c) => {
return c.json({ error: `handle not found: ${handle}` }, 404)
}
const user = users[0]!

if (!skipValidationChallenges.includes(challengeId)) {
// pass / fail
if (verifiedRewards.includes(challengeId)) {
if (!user.isVerified) {
return c.json({ error: 'denied' }, 400)
}
}
if (openRewards.includes(challengeId)) {
const userScore = await getUserNormalizedScore(
HashId.parse(user.id),
user.wallet
)

// Reward attestation proportional to user score confidence
if (userScore.overallScore < (amount as number) / rewardAmountRatio) {
if (userScore.overallScore < -1000) {
return c.json({ error: 'denied' }, 400)
}

// Custom rules for specific challenges
if (challengeId === 'e') {
if (!user.isVerified) {
return c.json({ error: 'denied' }, 400)
}
}
console.log('userScore', userScore, user)
}

try {
const bnAmount = SolanaUtils.uiAudioToBNWaudio(amount)
const identifier = SolanaUtils.constructTransferId(
Expand Down
2 changes: 0 additions & 2 deletions packages/mobile/src/app/Drawers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ import { SignOutConfirmationDrawer } from 'app/components/sign-out-confirmation-
import { StripeOnrampDrawer } from 'app/components/stripe-onramp-drawer'
import { SupportersInfoDrawer } from 'app/components/supporters-info-drawer'
import { TransferAudioMobileDrawer } from 'app/components/transfer-audio-mobile-drawer'
import { TrendingRewardsDrawer } from 'app/components/trending-rewards-drawer'
import { VerificationErrorDrawer } from 'app/components/verification-error-drawer/VerificationErrorDrawer'
import { VerificationSuccessDrawer } from 'app/components/verification-success-drawer/VerificationSuccessDrawer'
import { WaitForDownloadDrawer } from 'app/components/wait-for-download-drawer'
Expand Down Expand Up @@ -107,7 +106,6 @@ export const NativeDrawer = (props: NativeDrawerProps) => {

const commonDrawersMap: { [Modal in Modals]?: ComponentType } = {
TiersExplainer: TiersExplainerDrawer,
TrendingRewardsExplainer: TrendingRewardsDrawer,
ChallengeRewards: ChallengeRewardsDrawer,
ClaimAllRewards: ClaimAllRewardsDrawer,
APIRewardsExplainer: ApiRewardsDrawer,
Expand Down
72 changes: 0 additions & 72 deletions packages/mobile/src/components/audio-rewards/RewardsBanner.tsx

This file was deleted.

1 change: 0 additions & 1 deletion packages/mobile/src/components/audio-rewards/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export * from '../core/IconAudioBadge'
export * from './TiersExplainerDrawer'
export * from './RewardsBanner'
export * from './TierText'
2 changes: 1 addition & 1 deletion packages/mobile/src/components/drawer/DrawerHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const useStyles = makeStyles(({ spacing }) => ({
alignItems: 'center',
justifyContent: 'center',
paddingVertical: spacing(2),
paddingHorizontal: spacing(8),
paddingHorizontal: spacing(10),
zIndex: zIndex.DRAWER_HEADER
},

Expand Down
Loading