Skip to content

Commit

Permalink
NNS1-3548: Add compare functions for projects table (#6283)
Browse files Browse the repository at this point in the history
# Motivation

We want to allow the user to change the order in the projects table by
clicking on the table headers, similar to the neurons table.
When clicking the "Nervous Systems" header, the projects should be
ordered alphabetically by name.
When clicking the "Neurons" header, the projects should be ordered
number of neurons.
When clicking the "Stake" header, the projects should be ordered by:
1. USD value of the stake
2. Projects without exchange rate but positive number of neurons before
projects with zero neurons.
3. Within projects with the same (probably 0) USD stake, ICP should be
sorted before others.

This PR adds the sorting functions.
It does not add the functionality in the table.

# Changes

1. Add necessary compare functions.

# Tests

1. Unit tests added.
2. Tested manually (with additional changes) at
https://qsgjb-riaaa-aaaaa-aaaga-cai.dskloet-ingress.devenv.dfinity.network/tokens/

# Todos

- [ ] Add entry to changelog (if necessary).
not yet
  • Loading branch information
dskloetd authored Jan 29, 2025
1 parent 5391963 commit 3c0d32b
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
18 changes: 18 additions & 0 deletions frontend/src/lib/utils/staking.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,28 @@ const comparePositiveNeuronsFirst = createDescendingComparator(
(project: TableProject) => (project.neuronCount ?? 0) > 0
);

export const compareByNeuronCount = createDescendingComparator(
(project: TableProject) => project.neuronCount
);

export const compareByProjectTitle = createAscendingComparator(
(project: TableProject) => project.title.toLowerCase()
);

export const compareByStakeInUsd = createDescendingComparator(
(project: TableProject) => getUsdStake(project)
);

// This is used when clicking the "Stake" header, but in addition to sorting
// by stake, it has a number of tie breakers.
// Note that it tries to sort by USD stake but also sorts tokens with neurons
// above tokens without neurons if there is no exchange rate for that project.
export const compareByStake = mergeComparators([
compareByStakeInUsd,
comparePositiveNeuronsFirst,
compareIcpFirst,
]);

export const sortTableProjects = (projects: TableProject[]): TableProject[] => {
return [...projects].sort(
mergeComparators([
Expand Down
80 changes: 80 additions & 0 deletions frontend/src/tests/lib/utils/staking.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ import {
} from "$lib/constants/canister-ids.constants";
import type { Universe } from "$lib/types/universe";
import {
compareByNeuronCount,
compareByStake,
compareByStakeInUsd,
getTableProjects,
getTotalStakeInUsd,
sortTableProjects,
Expand Down Expand Up @@ -619,6 +622,83 @@ describe("staking.utils", () => {
});
});

describe("compareByNeuronCount", () => {
it("should compare by number of neurons", () => {
const project1 = {
...mockTableProject,
neuronCount: 1,
};
const project2 = {
...mockTableProject,
neuronCount: 2,
};

expect(compareByNeuronCount(project1, project2)).toEqual(1);
});
});

describe("compareByStakeInUsd", () => {
it("should compare by USD balance", () => {
const project1 = {
...mockTableProject,
stakeInUsd: 1,
};
const project2 = {
...mockTableProject,
stakeInUsd: 2,
};

expect(compareByStakeInUsd(project1, project2)).toEqual(1);
});
});

describe("compareByStake", () => {
it("should compare by USD stake", () => {
const project1 = {
...mockTableProject,
stakeInUsd: 1,
};
const project2 = {
...mockTableProject,
stakeInUsd: 2,
};

expect(compareByStake(project1, project2)).toEqual(1);
});

it("should compare projects with neurons before projects without neurons, if neither has a stake in USD", () => {
const project1 = {
...mockTableProject,
stakeInUsd: undefined,
neuronCount: 0,
};
const project2 = {
...mockTableProject,
stakeInUsd: undefined,
neuronCount: 1,
};

expect(compareByStake(project1, project2)).toEqual(1);
});

it("should compare ICP before other projects, if neither have neurons", () => {
const project1 = {
...mockTableProject,
stakeInUsd: undefined,
neuronCount: 0,
universeId: principal(2).toText(),
};
const project2 = {
...mockTableProject,
stakeInUsd: undefined,
neuronCount: 0,
universeId: OWN_CANISTER_ID_TEXT,
};

expect(compareByStake(project1, project2)).toEqual(1);
});
});

describe("sortTableProjects", () => {
const icpDomKey = OWN_CANISTER_ID_TEXT;
const snsUniverseId = principal(2).toText();
Expand Down

0 comments on commit 3c0d32b

Please sign in to comment.