From e4f59961284559708725717716323613ca8737ec Mon Sep 17 00:00:00 2001 From: Ray Lin <137183702+ruijialin-avalabs@users.noreply.github.com> Date: Fri, 13 Dec 2024 10:38:05 -0500 Subject: [PATCH] Update Staking simple flow node sorting and selection logic (#2154) --- .../app/hooks/earn/useSearchNode.ts | 2 + .../app/services/earn/utils.test.ts | 42 +++++++++++++++++++ .../core-mobile/app/services/earn/utils.ts | 20 +++++++-- 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/packages/core-mobile/app/hooks/earn/useSearchNode.ts b/packages/core-mobile/app/hooks/earn/useSearchNode.ts index 6d7a958d1d..5217f4e0ec 100644 --- a/packages/core-mobile/app/hooks/earn/useSearchNode.ts +++ b/packages/core-mobile/app/hooks/earn/useSearchNode.ts @@ -42,8 +42,10 @@ export const useSearchNode = ({ stakingAmount, stakingEndTime, minUpTime: 98, + maxFee: 4, isEndTimeOverOneYear }) + if (filteredValidators.length === 0) { Logger.info(noMatchError.message) return { validator: undefined, error: noMatchError } diff --git a/packages/core-mobile/app/services/earn/utils.test.ts b/packages/core-mobile/app/services/earn/utils.test.ts index 17f897b027..67d6512a66 100644 --- a/packages/core-mobile/app/services/earn/utils.test.ts +++ b/packages/core-mobile/app/services/earn/utils.test.ts @@ -210,6 +210,48 @@ describe('getRandomValidator function', () => { const result = getRandomValidator([]) expect(result).toBe(undefined) }) + + it('should return first item by end time if staking end time is over one year', () => { + const result = getRandomValidator( + mockValidators.validators as unknown as NodeValidators, + true + ) + expect(result).toBe(mockValidators.validators[0]) + }) + + it('should return first item if only one validator matches the lowest delegation fee', () => { + const validators = mockValidators.validators.map((validator, index) => { + if (index === 0) { + return { ...validator, delegationFee: '1.0000' } + } + return validator + }) + const result = getRandomValidator(validators as unknown as NodeValidators) + expect(result).toBe(validators[0]) + }) + it('should return random validator from ones that matches the lowest delegation fee', () => { + const validators = mockValidators.validators.map((validator, index) => { + if (index <= 1) { + return { ...validator, delegationFee: '1.0000' } + } + return validator + }) + const result = getRandomValidator(validators as unknown as NodeValidators) + const nodeIds = validators.map(validator => validator.nodeID) + expect(nodeIds.includes(result.nodeID)).toBeTruthy() + }) + + it('should return random validator from top five of ones that matches the lowest delegation fee', () => { + const validators = mockValidators.validators.map((validator, index) => { + if (index <= 10) { + return { ...validator, delegationFee: '1.0000' } + } + return validator + }) + const result = getRandomValidator(validators as unknown as NodeValidators) + const topFive = validators.slice(0, 5).map(validator => validator.nodeID) + expect(topFive.includes(result.nodeID)).toBeTruthy() + }) }) describe('getAdvancedSortedValidators function', () => { diff --git a/packages/core-mobile/app/services/earn/utils.ts b/packages/core-mobile/app/services/earn/utils.ts index 78f9d066d9..ab29aca331 100644 --- a/packages/core-mobile/app/services/earn/utils.ts +++ b/packages/core-mobile/app/services/earn/utils.ts @@ -237,8 +237,8 @@ export const getSimpleSortedValidators = ( } return [...validators].sort( (a, b): number => - Number(b.uptime) - Number(a.uptime) || Number(a.delegationFee) - Number(b.delegationFee) || + Number(b.uptime) - Number(a.uptime) || (peers === undefined ? 0 : comparePeerVersion( @@ -250,7 +250,7 @@ export const getSimpleSortedValidators = ( /** * - * @param validators input to take random item from, + * @param validators input sorted by delegationFee, uptime and node version to take random item from, * @param isEndTimeOverOneYear boolean indicating if the stake end time is over one year * @returns random item from either top 5 items in the array or all of the items in the array */ @@ -262,9 +262,23 @@ export const getRandomValidator = ( // get the first item in the array sorted by end time return validators.at(0) as NodeValidator } - const endIndex = validators.length >= 5 ? 4 : validators.length - 1 + + // get the validators with lowest delegation fee + const validatorsWithLowestFee = validators.filter( + validator => validator.delegationFee === validators[0]?.delegationFee + ) + + // if there is only one validator with the lowest fee, return it + if (validatorsWithLowestFee.length === 1) { + return validatorsWithLowestFee[0] as NodeValidator + } + + // if there are more than 2 validators with the lowest fee, return a random one between the 2-5 validators + const endIndex = + validatorsWithLowestFee.length >= 5 ? 4 : validators.length - 1 const randomIndex = random(0, endIndex) const matchedValidator = validators.at(randomIndex) + return matchedValidator as NodeValidator }