From 35a58dcdfe47b6721419a7d1b15af8b04418041f Mon Sep 17 00:00:00 2001 From: wa0x6e <495709+wa0x6e@users.noreply.github.com> Date: Fri, 29 Aug 2025 01:44:29 +0400 Subject: [PATCH 1/2] feat: pull overriding strategies from strategies list --- src/helpers/strategies.ts | 7 ++ src/helpers/utils.ts | 35 ++-------- test/unit/helpers/utils.test.ts | 114 ++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 29 deletions(-) create mode 100644 test/unit/helpers/utils.test.ts diff --git a/src/helpers/strategies.ts b/src/helpers/strategies.ts index 98915ee1..07ef42db 100644 --- a/src/helpers/strategies.ts +++ b/src/helpers/strategies.ts @@ -19,6 +19,7 @@ const URI = new URL( let consecutiveFailsCount = 0; let shouldStop = false; let strategies: Record = {}; +let overridingStrategies: string[] = []; async function loadStrategies() { const res = await snapshot.utils.getJSON(URI); @@ -40,6 +41,8 @@ async function loadStrategies() { })); strategies = Object.fromEntries(strategiesList.map(strategy => [strategy.id, strategy])); + + overridingStrategies = strategiesList.filter(s => s.override).map(s => s.id); } // Using a getter to avoid potential reference initialization issues @@ -47,6 +50,10 @@ export function getStrategies(): Record { return strategies; } +export function getOverridingStrategies(): string[] { + return overridingStrategies; +} + export async function initialize() { log.info('[strategies] Initial strategies load'); await loadStrategies(); diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts index ea9af0f0..ca8d3d7a 100644 --- a/src/helpers/utils.ts +++ b/src/helpers/utils.ts @@ -7,6 +7,7 @@ import { capture } from '@snapshot-labs/snapshot-sentry'; import snapshot from '@snapshot-labs/snapshot.js'; import { Response } from 'express'; import fetch from 'node-fetch'; +import { getOverridingStrategies } from './strategies'; const MAINNET_NETWORK_ID_WHITELIST = ['s', 'eth', 'arb1', 'oeth', 'sn', 'base', 'mnt', 'ape']; const TESTNET_NETWORK_ID_WHITELIST = ['s-tn', 'sep', 'curtis', 'linea-testnet', 'sn-sep']; @@ -62,36 +63,12 @@ export function rpcError(res, code, e, id) { }); } -export function hasStrategyOverride(strategies: any[]) { - const keywords = [ - '"aura-vlaura-vebal-with-overrides"', - '"balance-of-with-linear-vesting-power"', - '"balancer-delegation"', - '"cyberkongz"', - '"cyberkongz-v2"', - '"delegation"', - '"delegation-with-cap"', - '"delegation-with-overrides"', - '"erc20-balance-of-delegation"', - '"erc20-balance-of-fixed-total"', - '"erc20-balance-of-quadratic-delegation"', - '"erc20-votes-with-override"', - '"esd-delegation"', - '"ocean-dao-brightid"', - '"orbs-network-delegation"', - '"api-v2-override"', - '"rocketpool-node-operator-delegate-v8"', - '"eden-online-override"', - '"split-delegation"', - '"sonic-staked-balance"' - ]; +export function hasStrategyOverride(strategies: any[]): boolean { + if (!strategies?.length) return false; + const strategiesStr = JSON.stringify(strategies).toLowerCase(); - if (keywords.some(keyword => strategiesStr.includes(`"name":${keyword}`))) return true; - // Check for split-delegation with delegationOverride - const splitDelegation = strategies.filter(strategy => strategy.name === 'split-delegation'); - return ( - splitDelegation.length > 0 && - splitDelegation.some(strategy => strategy.params?.delegationOverride) + return getOverridingStrategies().some(strategyId => + strategiesStr.includes(`"name":"${strategyId}"`) ); } diff --git a/test/unit/helpers/utils.test.ts b/test/unit/helpers/utils.test.ts new file mode 100644 index 00000000..f5922808 --- /dev/null +++ b/test/unit/helpers/utils.test.ts @@ -0,0 +1,114 @@ +import * as strategies from '../../../src/helpers/strategies'; +import { hasStrategyOverride } from '../../../src/helpers/utils'; + +const OVERRIDING_STRATEGIES = ['delegation', 'delegation-with-cap']; + +// Mock the getOverridingStrategies function +jest.mock('../../../src/helpers/strategies'); +const mockGetOverridingStrategies = jest.mocked(strategies.getOverridingStrategies); + +describe('Utils', () => { + describe('hasStrategyOverride()', () => { + beforeEach(() => { + jest.clearAllMocks(); + mockGetOverridingStrategies.mockReturnValue(OVERRIDING_STRATEGIES); + }); + + it('should return false when strategies array is empty', () => { + expect(hasStrategyOverride([])).toBe(false); + }); + + it('should return false when no overriding strategies exist', () => { + const strategies = [ + { name: 'whitelist', network: '1', params: {} }, + { name: 'ticket', network: '1', params: {} } + ]; + + expect(hasStrategyOverride(strategies)).toBe(false); + }); + + it('should return true when an overriding strategy is used', () => { + const strategies = [ + { name: 'whitelist', network: '1', params: {} }, + { name: 'delegation', network: '1', params: {} } + ]; + + expect(hasStrategyOverride(strategies)).toBe(true); + }); + + it('should return true when multiple overriding strategies are used', () => { + const strategies = [ + { name: 'delegation', network: '1', params: {} }, + { name: 'delegation-with-cap', network: '1', params: {} } + ]; + + expect(hasStrategyOverride(strategies)).toBe(true); + }); + + it('should handle mixed case strategy names correctly', () => { + const strategies = [{ name: 'Delegation', network: '1', params: {} }]; + + expect(hasStrategyOverride(strategies)).toBe(true); + }); + + it('should handle inner strategies', () => { + const strategies = [ + { + name: 'multichain', + network: '1', + params: { + symbol: 'MULTI', + strategies: [ + { + name: 'erc20-balance-of', + network: '1', + params: { + address: '0x579cea1889991f68acc35ff5c3dd0621ff29b0c9', + decimals: 18 + } + }, + { + name: 'delegation', + network: '137', + params: { + delegationSpace: 'test.eth', + strategies: [ + { + name: 'erc20-balance-of', + params: { + address: '0xB9638272aD6998708de56BBC0A290a1dE534a578', + decimals: 18 + } + } + ] + } + } + ] + } + } + ]; + + expect(hasStrategyOverride(strategies)).toBe(true); + }); + + it('should not match when strategy id appears in other fields', () => { + const strategies = [ + { + name: 'whitelist', + network: '1', + params: { description: 'delegation' } + } + ]; + + expect(hasStrategyOverride(strategies)).toBe(false); + }); + + it('should handle empty getOverridingStrategies result', () => { + mockGetOverridingStrategies.mockReturnValue([]); + + const strategies = [{ name: 'delegation', network: '1', params: {} }]; + + expect(hasStrategyOverride(strategies)).toBe(false); + }); + }); +}); From 699420d8598522eac323cd16aa775299077a299a Mon Sep 17 00:00:00 2001 From: Wan <495709+wa0x6e@users.noreply.github.com> Date: Sun, 31 Aug 2025 02:34:46 +0900 Subject: [PATCH 2/2] Update src/helpers/utils.ts Co-authored-by: Chaitanya --- src/helpers/utils.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/helpers/utils.ts b/src/helpers/utils.ts index ca8d3d7a..d8ca0edf 100644 --- a/src/helpers/utils.ts +++ b/src/helpers/utils.ts @@ -64,8 +64,6 @@ export function rpcError(res, code, e, id) { } export function hasStrategyOverride(strategies: any[]): boolean { - if (!strategies?.length) return false; - const strategiesStr = JSON.stringify(strategies).toLowerCase(); return getOverridingStrategies().some(strategyId => strategiesStr.includes(`"name":"${strategyId}"`)