Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat(affiliates): Initial program implementation #1019

Closed
wants to merge 47 commits into from

Conversation

M-Ivan
Copy link
Contributor

@M-Ivan M-Ivan commented Sep 16, 2024

Pull request

This PR implements the foundational UI for the rewards program on the dYdX protocol. It is dependant on (v4-Localization-pr).

EDIT: This PR now depends on this other PR dydxprotocol/v4-localization#711

Note:
Components changes in this PR are extensions of the existing components, to avoid the risk of breaking changes on other views.

Pending implementations:

  • Backend integration
  • Rewards program banner
  • Affiliate disclaimer card
  • Community chart

Views

  • New: Affiliates/
    • AffiliateLeaderboard.tsx: Leaderboard for affiliates, uses load more pagination strategy.
    • AffiliateStats.tsx: Card with the current account stats as an affiliate for the dYdX protocol
    • ProgramCard.tsx: Card with VIP program info.
    • CommunityChart.tsx: A reactive chart displaying rewards program historical stats
    • CriteriaModal.tsx: A popup dialog with information for the different applicable tiers in the rewards program
    • LastUpdated.tsx: A reactive label that displays the last time the leaderboard synced with the historical data
    • ProgramStats.tsx: Card with rewards program historical stats
    • StatBox.tsx: Reusable cell component being used in ProgramStats, CriteriaModal and AffiliateStats.

Types

  • New: affiliates.ts
    • IAffiliateStats: Interface for a specific affiliate different stats.

Pages

  • New: affiliates/AffiliatesPage.tsx: Routable page for the affiliates UI (parent of all affiliate views).

Testing instructions

To test the feature out, you will require to setup v4-localization from this PR branch. After that you can navigate to /affiliates and the page will display.

@M-Ivan M-Ivan requested a review from a team as a code owner September 16, 2024 13:46
Copy link

vercel bot commented Sep 16, 2024

@M-Ivan is attempting to deploy a commit to the dYdX Trading Team on Vercel.

A member of the Team first needs to authorize it.

Copy link

vercel bot commented Oct 3, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
v4-staging ❌ Failed (Inspect) Oct 3, 2024 5:32pm
v4-testnet ❌ Failed (Inspect) Oct 3, 2024 5:32pm

.env.example Outdated
@@ -1,4 +1,5 @@
VITE_BASE_URL=
VITE_AFFILIATES_SERVER_BASE_URL="http://localhost:3000"
Copy link
Contributor

Choose a reason for hiding this comment

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

It would be better to have this endpoint added here!
https://github.com/dydxopsdao/v4-web/blob/main/public/configs/v1/env.json#L308
and then you can access it via useEndpointsConfig

}, []);

const fetchProgramStats = async () => {
const res = await axios.get(`http://localhost:3000/v1/community/program-stats`);
Copy link
Contributor

Choose a reason for hiding this comment

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

should we use VITE_AFFILIATES_SERVER_BASE_URL or endpoint config here for base url?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably creating an additional config for the affiliate server is worth it. I will check if its possible to adapt it and worst case we can call the BASE env var here.

Copy link
Contributor Author

@M-Ivan M-Ivan Oct 8, 2024

Choose a reason for hiding this comment

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

The config is not working for some reasson, also i cannot seem to be able to get the .env file read correctly in my local.
I am leaving the base url call atm.

Copy link
Contributor

Choose a reason for hiding this comment

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

Weird, ok we can leave it as is, and I can update it as needed as a follow up.

fetchLastUpdated();
}, []);

const fetchProgramStats = async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

For these fetches, lets put it all into a react-query hook, see:

export const useAffiliatesInfo = (dydxAddress?: string) => {

That way we don't need to do a fetch on every page load, and the hook can be reusable!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added hooks for leaderboard, communityChart and integrated some fetchs into the affiliates info hook.


const fetchAffiliateStats = async () => {
// Comment for testing with local data
const response = await axios.post('http://localhost:3000/v1/leaderboard/search', {
Copy link
Contributor

Choose a reason for hiding this comment

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

Lets leverage react-query here as well

return () => clearInterval(timer); // Cleanup the timer
}, []);

// Helper function to calculate "X mins ago"
Copy link
Contributor

Choose a reason for hiding this comment

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

for these time formating I wonder if we can leverage:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/RelativeTimeFormat

e.g

function timeAgo(timestamp: Date): string {
    const diffInSeconds = Math.floor((Date.now() - timestamp.getTime()) / 1000);

    const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });

    if (diffInSeconds < 60) {
        return 'updated just now';
    } else if (diffInSeconds < 3600) {
        const minutes = Math.floor(diffInSeconds / 60);
        return `updated ${rtf.format(-minutes, 'minute')}`;
    } else if (diffInSeconds < 86400) {
        const hours = Math.floor(diffInSeconds / 3600);
        return `updated ${rtf.format(-hours, 'hour')}`;
    } else {
        const days = Math.floor(diffInSeconds / 86400);
        return `updated ${rtf.format(-days, 'day')}`;
    }
}

useEffect(() => {
const timer = setInterval(() => {
setCurrentTime(new Date());
}, 60000); // Update every 60 seconds
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: can move numbers into a constant at the time of the file

Copy link
Contributor

@rosepuppy rosepuppy left a comment

Choose a reason for hiding this comment

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

oops sorry accidentally approved instead 😅

@alejoviola
Copy link
Contributor

alejoviola commented Oct 18, 2024

EDIT: This PR now depends on this other PR dydxprotocol/v4-localization#761 where I added a translation for chart empty state in affiliate program.

@tyleroooo
Copy link
Contributor

Can this PR be closed in favor of #1181 ?

@tinaszheng
Copy link
Contributor

@M-Ivan closing this in favor of #1181 - let me know if i should reopen!

@tinaszheng tinaszheng closed this Oct 31, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants