Skip to content

Feature / Trending tokens#2505

Open
sonytooo wants to merge 10 commits into
v2from
feature/trending-tokens
Open

Feature / Trending tokens#2505
sonytooo wants to merge 10 commits into
v2from
feature/trending-tokens

Conversation

@sonytooo

Copy link
Copy Markdown
Member
  • Add trending tokens to the DappsController. Later the dapps ctrl is planned to be renamed to the more generic name ExploreController to match to FE functionality

@sonytooo sonytooo self-assigned this Jun 24, 2026
@sonytooo sonytooo added the enhancement New feature or request label Jun 24, 2026
@PetromirDev

Copy link
Copy Markdown
Member

/review

@github-actions

Copy link
Copy Markdown

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
🔒 No security concerns identified
✅ No TODO sections
⚡ Recommended focus areas for review

Mutable state exposure

The trendingTokens getter returns the internal #trendingTokens array reference directly. External callers can mutate the array or its items, corrupting the controller's internal state and causing stale or inconsistent UI data.

get trendingTokens(): TrendingToken[] {
  return this.#trendingTokens
}
Unhandled rejection from public method

The public continuouslyUpdateTrendingTokens method is the RecurringTimeout callback. Its catch block mutates the interval timeout and then re-throws the error, so any direct caller receives an unhandled rejection instead of a safely emitted error.

async continuouslyUpdateTrendingTokens() {
  if (this.#continuouslyUpdateTrendingTokensPromise) {
    await this.#continuouslyUpdateTrendingTokensPromise

    return
  }

  this.#continuouslyUpdateTrendingTokensPromise = this.#continuouslyUpdateTrendingTokens()
    .catch((err) => {
      this.#updateTrendingTokensInterval.updateTimeout({
        timeout: TRENDING_TOKENS_FAILED_UPDATE_INTERVAL
      })
      throw err
    })
    .finally(() => {
      this.#continuouslyUpdateTrendingTokensPromise = undefined
    })

  await this.#continuouslyUpdateTrendingTokensPromise
}
Parallel storage write risk

The trending-tokens background loop awaits this.#storage.set('trending', ...). This can run concurrently with other storage writes in the same controller (e.g., the un-awaited void this.#storage.set('dappsV2', ...) in #syncDappsBlacklistedStatusWithPhishing). Per project invariants, parallel storage.set() calls risk corrupting persisted state.

await this.#storage.set('trending', { updatedAt, tokens: this.#trendingTokens })

Comment on lines +186 to +191
// Trending tokens are refreshed server-side every 10 minutes; poll at the same cadence.
this.#updateTrendingTokensInterval = new RecurringTimeout(
() => this.continuouslyUpdateTrendingTokens(),
TRENDING_TOKENS_UPDATE_INTERVAL,
this.emitError.bind(this)
)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we move it to continuous updates?

Comment on lines +561 to +567
this.#continuouslyUpdateTrendingTokensPromise = this.#continuouslyUpdateTrendingTokens()
.catch((err) => {
this.#updateTrendingTokensInterval.updateTimeout({
timeout: TRENDING_TOKENS_FAILED_UPDATE_INTERVAL
})
throw err
})

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we rethrow the error here and not emit an error?

Comment thread src/consts/intervals.ts
export const PHISHING_INACTIVE_UPDATE_INTERVAL = 6 * 60 * 60 * 1000 // 6 hrs
export const PHISHING_ACTIVE_UPDATE_INTERVAL = 15 * 60 * 1000 // 15 minutes
export const PHISHING_FAILED_TO_GET_UPDATE_INTERVAL = 600000 // 10 minutes
export const TRENDING_TOKENS_UPDATE_INTERVAL = 10 * 60 * 1000 // 10 minutes

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this way too often? There are 30 tokens, yes, but we are updating the tokens regardless of whether the extension is active or not. Imo, we shoud run the interval while the extension is active and simply update on popup open if the last update is more than X minutes ago. If the interval runs less often then it will be okay to run it always (e.g., every 4+ hours)

@JIOjosBG JIOjosBG self-requested a review July 10, 2026 11:37

@JIOjosBG JIOjosBG left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i updated properties on the backend to reduce request size, you can merge this here #2529

…med-payload

Trending tokens/ remove duplicate properties
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request Review effort 3/5

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants