From 5892d45171d853e0fc741967d8c8442bce842fef Mon Sep 17 00:00:00 2001 From: tamir Date: Wed, 18 Feb 2026 10:43:28 +0200 Subject: [PATCH 1/6] Added lifecycle hooks to solver table --- .../solver/content-types/solver/lifecycles.ts | 254 ++++++++++++++++++ 1 file changed, 254 insertions(+) create mode 100644 src/api/solver/content-types/solver/lifecycles.ts diff --git a/src/api/solver/content-types/solver/lifecycles.ts b/src/api/solver/content-types/solver/lifecycles.ts new file mode 100644 index 0000000..2a8d4ff --- /dev/null +++ b/src/api/solver/content-types/solver/lifecycles.ts @@ -0,0 +1,254 @@ +import { errors } from "@strapi/utils"; + +export default { + async beforeCreate(event) { + try { + await updateActiveNetworks(event); + await updateServiceFeeEnabled(event); + } catch (error) { + console.error("Error in beforeCreate:", error); + throw new errors.ValidationError(error.message || "Error processing solver data"); + } + }, + + async beforeUpdate(event) { + try { + await updateActiveNetworks(event); + await updateServiceFeeEnabled(event); + } catch (error) { + console.error("Error in beforeUpdate:", error); + throw new errors.ValidationError(error.message || "Error processing solver data"); + } + }, + + async afterCreate(event) { + try { + const { result } = event; + if (result && result.id) { + await calculateActiveNetworksForSolver(result.id); + await updateServiceFeeEnabledForSolver(result.id); + } + } catch (error) { + console.error("Error in afterCreate:", error); + } + }, + + async afterUpdate(event) { + try { + const { result } = event; + if (result && result.id) { + await calculateActiveNetworksForSolver(result.id); + await updateServiceFeeEnabledForSolver(result.id); + } + } catch (error) { + console.error("Error in afterUpdate:", error); + } + } +}; + +interface SolverData { + activeNetworks?: string[]; + hasActiveNetworks?: boolean; + isServiceFeeEnabled?: boolean; + solver_networks?: any; +} + +interface StrapiEvent { + params: { + data: SolverData; + where?: { + id: number; + }; + }; + result?: { + id: number; + }; +} + +async function updateActiveNetworks(event: StrapiEvent) { + const { data, where } = event.params; + const solverData: SolverData = data; + + if (where && !data.solver_networks) { + try { + const solver = await strapi.entityService.findOne( + 'api::solver.solver', + where.id, + { populate: ['solver_networks.network'] } + ); + + if (solver) { + await calculateActiveNetworks(solver, solverData); + } + } catch (error) { + console.error(`Error fetching solver data for id ${where.id}:`, error); + throw new errors.ApplicationError(`Failed to fetch solver data: ${error.message}`); + } + } +} + +// This function will be called after create/update to ensure relations are established +export async function calculateActiveNetworksForSolver(solverId: number): Promise { + try { + const solver = await strapi.entityService.findOne( + 'api::solver.solver', + solverId, + { populate: ['solver_networks.network'] } + ); + + if (solver) { + const data: SolverData = {}; + await calculateActiveNetworks(solver, data); + + if (data.activeNetworks || data.hasActiveNetworks !== undefined) { + await strapi.entityService.update( + 'api::solver.solver', + solverId, + { data } + ); + } + } + } catch (error) { + console.error(`Error calculating active networks for solver ${solverId}:`, error); + throw new errors.ApplicationError(`Failed to calculate active networks: ${error.message}`); + } +} + +export async function updateServiceFeeEnabledForSolver(solverId: number): Promise { + try { + const solver = await strapi.entityService.findOne( + 'api::solver.solver', + solverId, + { + populate: { + solver_bonding_pools: { + fields: ['name', 'joinedOn'] + } + } + } + ); + + if (solver) { + const data: SolverData = {}; + await calculateServiceFeeEnabled(solver, data); + + if (data.isServiceFeeEnabled !== undefined) { + await strapi.entityService.update( + 'api::solver.solver', + solverId, + { data } + ); + } + } + } catch (error) { + console.error(`Error updating service fee enabled for solver ${solverId}:`, error); + throw new errors.ApplicationError(`Failed to update service fee status: ${error.message}`); + } +} + +interface Solver { + id: number; + solver_networks?: Array<{ + active?: boolean; + network?: { + name?: string; + }; + }>; + solver_bonding_pools?: Array<{ + name?: string; + joinedOn?: string; + }>; + isColocated?: string; +} + +async function calculateActiveNetworks(solver: Solver, data: SolverData): Promise { + if (!solver.solver_networks) { + data.activeNetworks = []; + data.hasActiveNetworks = false; + return; + } + + // Filter active networks and extract their names + const activeNetworkNames = solver.solver_networks + .filter(network => network.active) + .map(network => network.network?.name) + .filter(Boolean) as string[]; // Remove any undefined values + + data.activeNetworks = activeNetworkNames; + data.hasActiveNetworks = activeNetworkNames.length > 0; +} + +async function updateServiceFeeEnabled(event: StrapiEvent): Promise { + const { data, where } = event.params; + const solverData: SolverData = data; + + if (where) { + try { + const solver = await strapi.entityService.findOne( + 'api::solver.solver', + where.id, + { + populate: { + solver_bonding_pools: { + fields: ['name', 'joinedOn'] + } + } + } + ); + + if (solver) { + await calculateServiceFeeEnabled(solver, solverData); + } + } catch (error) { + console.error(`Error fetching solver data for service fee calculation (id ${where.id}):`, error); + throw new errors.ApplicationError(`Failed to fetch solver data for service fee calculation: ${error.message}`); + } + } + // For create operation, we handle it in afterCreate since we need the ID +} + +async function calculateServiceFeeEnabled(solver: Solver, data: SolverData): Promise { + data.isServiceFeeEnabled = false; + + if (!solver.solver_bonding_pools || solver.solver_bonding_pools.length === 0) { + return; + } + + try { + const currentDate = new Date(); + + for (const bondingPool of solver.solver_bonding_pools) { + if (!bondingPool.joinedOn) { + continue; + } + + const joinedDate = new Date(bondingPool.joinedOn); + const monthsDifference = getMonthsDifference(joinedDate, currentDate); + + if (bondingPool.name === "CoW" && solver.isColocated === "No") { + if (monthsDifference >= 6) { + data.isServiceFeeEnabled = true; + return; + } + } + // Colocated bonding pool + else if (solver.isColocated === "Yes") { + if (monthsDifference >= 3) { + data.isServiceFeeEnabled = true; + return; + } + } + // For partial colocated, we'll treat it as not colocated + } + } catch (error) { + console.error(`Error calculating service fee enabled status:`, error); + throw new errors.ApplicationError(`Failed to calculate service fee status: ${error.message}`); + } +} + +// Helper function to calculate months difference between two dates +function getMonthsDifference(startDate: Date, endDate: Date): number { + const years = endDate.getFullYear() - startDate.getFullYear(); + const months = endDate.getMonth() - startDate.getMonth(); + return years * 12 + months; +} From a7e2fb47fbb7e84410c9e34db1023214c38077b8 Mon Sep 17 00:00:00 2001 From: tamir Date: Wed, 18 Feb 2026 10:51:17 +0200 Subject: [PATCH 2/6] Updated lifecycle hooks to solver table --- .../solver/content-types/solver/lifecycles.ts | 83 ------------------- 1 file changed, 83 deletions(-) diff --git a/src/api/solver/content-types/solver/lifecycles.ts b/src/api/solver/content-types/solver/lifecycles.ts index 2a8d4ff..16ff7cf 100644 --- a/src/api/solver/content-types/solver/lifecycles.ts +++ b/src/api/solver/content-types/solver/lifecycles.ts @@ -20,30 +20,6 @@ export default { throw new errors.ValidationError(error.message || "Error processing solver data"); } }, - - async afterCreate(event) { - try { - const { result } = event; - if (result && result.id) { - await calculateActiveNetworksForSolver(result.id); - await updateServiceFeeEnabledForSolver(result.id); - } - } catch (error) { - console.error("Error in afterCreate:", error); - } - }, - - async afterUpdate(event) { - try { - const { result } = event; - if (result && result.id) { - await calculateActiveNetworksForSolver(result.id); - await updateServiceFeeEnabledForSolver(result.id); - } - } catch (error) { - console.error("Error in afterUpdate:", error); - } - } }; interface SolverData { @@ -87,65 +63,6 @@ async function updateActiveNetworks(event: StrapiEvent) { } } -// This function will be called after create/update to ensure relations are established -export async function calculateActiveNetworksForSolver(solverId: number): Promise { - try { - const solver = await strapi.entityService.findOne( - 'api::solver.solver', - solverId, - { populate: ['solver_networks.network'] } - ); - - if (solver) { - const data: SolverData = {}; - await calculateActiveNetworks(solver, data); - - if (data.activeNetworks || data.hasActiveNetworks !== undefined) { - await strapi.entityService.update( - 'api::solver.solver', - solverId, - { data } - ); - } - } - } catch (error) { - console.error(`Error calculating active networks for solver ${solverId}:`, error); - throw new errors.ApplicationError(`Failed to calculate active networks: ${error.message}`); - } -} - -export async function updateServiceFeeEnabledForSolver(solverId: number): Promise { - try { - const solver = await strapi.entityService.findOne( - 'api::solver.solver', - solverId, - { - populate: { - solver_bonding_pools: { - fields: ['name', 'joinedOn'] - } - } - } - ); - - if (solver) { - const data: SolverData = {}; - await calculateServiceFeeEnabled(solver, data); - - if (data.isServiceFeeEnabled !== undefined) { - await strapi.entityService.update( - 'api::solver.solver', - solverId, - { data } - ); - } - } - } catch (error) { - console.error(`Error updating service fee enabled for solver ${solverId}:`, error); - throw new errors.ApplicationError(`Failed to update service fee status: ${error.message}`); - } -} - interface Solver { id: number; solver_networks?: Array<{ From 7ea094820d8d3a77c5c6a3bfba60a31c33705f01 Mon Sep 17 00:00:00 2001 From: tamir Date: Wed, 18 Feb 2026 12:42:17 +0200 Subject: [PATCH 3/6] Updated lifecycle hooks to solver table --- src/api/solver/content-types/solver/lifecycles.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/solver/content-types/solver/lifecycles.ts b/src/api/solver/content-types/solver/lifecycles.ts index 16ff7cf..fd58923 100644 --- a/src/api/solver/content-types/solver/lifecycles.ts +++ b/src/api/solver/content-types/solver/lifecycles.ts @@ -54,7 +54,7 @@ async function updateActiveNetworks(event: StrapiEvent) { ); if (solver) { - await calculateActiveNetworks(solver, solverData); + await calculateActiveNetworks(solver as Solver, solverData); } } catch (error) { console.error(`Error fetching solver data for id ${where.id}:`, error); @@ -114,7 +114,7 @@ async function updateServiceFeeEnabled(event: StrapiEvent): Promise { ); if (solver) { - await calculateServiceFeeEnabled(solver, solverData); + await calculateServiceFeeEnabled(solver as Solver, solverData); } } catch (error) { console.error(`Error fetching solver data for service fee calculation (id ${where.id}):`, error); From b15c2605ef216709c2b028267e044a51f6bce7ec Mon Sep 17 00:00:00 2001 From: tamir Date: Thu, 19 Feb 2026 10:19:46 +0200 Subject: [PATCH 4/6] Addressed cr notes --- .../solver/content-types/solver/lifecycles.ts | 76 +++++++++++-------- src/utils/date.ts | 15 ++++ 2 files changed, 58 insertions(+), 33 deletions(-) create mode 100644 src/utils/date.ts diff --git a/src/api/solver/content-types/solver/lifecycles.ts b/src/api/solver/content-types/solver/lifecycles.ts index fd58923..d07f81e 100644 --- a/src/api/solver/content-types/solver/lifecycles.ts +++ b/src/api/solver/content-types/solver/lifecycles.ts @@ -1,4 +1,8 @@ import { errors } from "@strapi/utils"; +import { getMonthsDifference } from "../../../../utils/date"; + +const COW_BONDING_POOL_SERVICE_FEE_TH: number = 6; +const COLOCATED_BONDING_POOL_SERVICE_FEE_TH: number = 3; export default { async beforeCreate(event) { @@ -114,7 +118,7 @@ async function updateServiceFeeEnabled(event: StrapiEvent): Promise { ); if (solver) { - await calculateServiceFeeEnabled(solver as Solver, solverData); + await setServiceFeeEnabled(solver as Solver, solverData); } } catch (error) { console.error(`Error fetching solver data for service fee calculation (id ${where.id}):`, error); @@ -124,48 +128,54 @@ async function updateServiceFeeEnabled(event: StrapiEvent): Promise { // For create operation, we handle it in afterCreate since we need the ID } -async function calculateServiceFeeEnabled(solver: Solver, data: SolverData): Promise { - data.isServiceFeeEnabled = false; - +/** + * Determines if a solver is eligible for service fees based on bonding pool criteria. + * Pure function that checks eligibility based on time thresholds: + * - 6+ months for non-colocated CoW pools + * - 3+ months for colocated pools + * @param solver The solver entity to check + * @returns Boolean indicating if the solver is eligible for service fees + */ +function isEligibleForServiceFee(solver: Solver): boolean { if (!solver.solver_bonding_pools || solver.solver_bonding_pools.length === 0) { - return; + return false; } - try { - const currentDate = new Date(); + const currentDate = new Date(); - for (const bondingPool of solver.solver_bonding_pools) { - if (!bondingPool.joinedOn) { - continue; - } + for (const bondingPool of solver.solver_bonding_pools) { + if (!bondingPool.joinedOn) { + continue; + } - const joinedDate = new Date(bondingPool.joinedOn); - const monthsDifference = getMonthsDifference(joinedDate, currentDate); + const joinedDate = new Date(bondingPool.joinedOn); + const monthsDifference = getMonthsDifference(joinedDate, currentDate); - if (bondingPool.name === "CoW" && solver.isColocated === "No") { - if (monthsDifference >= 6) { - data.isServiceFeeEnabled = true; - return; - } + if (bondingPool.name === "CoW" && solver.isColocated === "No") { + if (monthsDifference >= COW_BONDING_POOL_SERVICE_FEE_TH) { + return true; } - // Colocated bonding pool - else if (solver.isColocated === "Yes") { - if (monthsDifference >= 3) { - data.isServiceFeeEnabled = true; - return; - } + } + else if (solver.isColocated === "Yes") { + if (monthsDifference >= COLOCATED_BONDING_POOL_SERVICE_FEE_TH) { + return true; } - // For partial colocated, we'll treat it as not colocated } - } catch (error) { - console.error(`Error calculating service fee enabled status:`, error); - throw new errors.ApplicationError(`Failed to calculate service fee status: ${error.message}`); + // For partial colocated, we'll treat it as not colocated } + + return false; } -// Helper function to calculate months difference between two dates -function getMonthsDifference(startDate: Date, endDate: Date): number { - const years = endDate.getFullYear() - startDate.getFullYear(); - const months = endDate.getMonth() - startDate.getMonth(); - return years * 12 + months; +/** + * Sets the isServiceFeeEnabled flag in the solver data based on eligibility. + * Uses the pure function isEligibleForServiceFee to determine eligibility. + */ +async function setServiceFeeEnabled(solver: Solver, data: SolverData): Promise { + try { + data.isServiceFeeEnabled = isEligibleForServiceFee(solver); + } catch (error) { + console.error(`Error setting service fee enabled status:`, error); + throw new errors.ApplicationError(`Failed to set service fee status: ${error.message}`); + } } diff --git a/src/utils/date.ts b/src/utils/date.ts new file mode 100644 index 0000000..e036eff --- /dev/null +++ b/src/utils/date.ts @@ -0,0 +1,15 @@ +/** + * Date utility functions + */ + +/** + * Calculate the number of months between two dates + * @param startDate The start date + * @param endDate The end date + * @returns The number of months between the two dates + */ +export function getMonthsDifference(startDate: Date, endDate: Date): number { + const years = endDate.getFullYear() - startDate.getFullYear(); + const months = endDate.getMonth() - startDate.getMonth(); + return years * 12 + months; +} From f36bff8db9b83192bc9a389bf2e677689225cb46 Mon Sep 17 00:00:00 2001 From: tamir Date: Thu, 26 Feb 2026 09:59:05 +0200 Subject: [PATCH 5/6] Addressed cr notes --- .../solver/content-types/solver/lifecycles.ts | 42 +++++++++++++------ src/utils/date.ts | 24 +++++++++-- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/src/api/solver/content-types/solver/lifecycles.ts b/src/api/solver/content-types/solver/lifecycles.ts index d07f81e..c23b5d4 100644 --- a/src/api/solver/content-types/solver/lifecycles.ts +++ b/src/api/solver/content-types/solver/lifecycles.ts @@ -3,9 +3,10 @@ import { getMonthsDifference } from "../../../../utils/date"; const COW_BONDING_POOL_SERVICE_FEE_TH: number = 6; const COLOCATED_BONDING_POOL_SERVICE_FEE_TH: number = 3; +const COW_CONDING_POOL_NAME: string = "CoW"; export default { - async beforeCreate(event) { + async afterCreate(event) { try { await updateActiveNetworks(event); await updateServiceFeeEnabled(event); @@ -15,7 +16,7 @@ export default { } }, - async beforeUpdate(event) { + async afterUpdate(event) { try { await updateActiveNetworks(event); await updateServiceFeeEnabled(event); @@ -58,7 +59,7 @@ async function updateActiveNetworks(event: StrapiEvent) { ); if (solver) { - await calculateActiveNetworks(solver as Solver, solverData); + await updateActiveNetworksData(solver as Solver, solverData); } } catch (error) { console.error(`Error fetching solver data for id ${where.id}:`, error); @@ -82,21 +83,35 @@ interface Solver { isColocated?: string; } -async function calculateActiveNetworks(solver: Solver, data: SolverData): Promise { - if (!solver.solver_networks) { - data.activeNetworks = []; - data.hasActiveNetworks = false; - return; +/** + * Extracts active network names from solver networks + * @param solverNetworks Array of solver network objects + * @returns Array of active network names + */ +function getActiveNetworks(solverNetworks?: Array<{ + active?: boolean; + network?: { + name?: string; + }; +}>): string[] { + if (!solverNetworks) { + return []; } - // Filter active networks and extract their names - const activeNetworkNames = solver.solver_networks + return solverNetworks .filter(network => network.active) .map(network => network.network?.name) .filter(Boolean) as string[]; // Remove any undefined values +} - data.activeNetworks = activeNetworkNames; - data.hasActiveNetworks = activeNetworkNames.length > 0; +/** + * Updates the solver data with active network information + * This function mutates the data object by setting activeNetworks and hasActiveNetworks properties + */ +async function updateActiveNetworksData(solver: Solver, data: SolverData): Promise { + const activeNetworks = getActiveNetworks(solver.solver_networks); + data.hasActiveNetworks = activeNetworks.length > 0; + data.activeNetworks = activeNetworks; } async function updateServiceFeeEnabled(event: StrapiEvent): Promise { @@ -144,6 +159,7 @@ function isEligibleForServiceFee(solver: Solver): boolean { const currentDate = new Date(); for (const bondingPool of solver.solver_bonding_pools) { + // Skip if joinedOn field is not set (not a mandatory field) if (!bondingPool.joinedOn) { continue; } @@ -151,7 +167,7 @@ function isEligibleForServiceFee(solver: Solver): boolean { const joinedDate = new Date(bondingPool.joinedOn); const monthsDifference = getMonthsDifference(joinedDate, currentDate); - if (bondingPool.name === "CoW" && solver.isColocated === "No") { + if (bondingPool.name === COW_CONDING_POOL_NAME && solver.isColocated === "No") { if (monthsDifference >= COW_BONDING_POOL_SERVICE_FEE_TH) { return true; } diff --git a/src/utils/date.ts b/src/utils/date.ts index e036eff..a85e5c7 100644 --- a/src/utils/date.ts +++ b/src/utils/date.ts @@ -3,13 +3,31 @@ */ /** - * Calculate the number of months between two dates + * Calculate the actual number of months between two dates + * This function considers the full date (year, month, and day) to determine + * if a complete month has passed between the start and end dates. + * + * Examples: + * - 31/01/2026 to 01/02/2026 = 0 months (only 1 day difference) + * - 01/01/2026 to 02/01/2026 = 0 months (only 1 day difference) + * - 01/01/2026 to 01/02/2026 = 1 month (exactly 1 month) + * - 15/01/2026 to 20/02/2026 = 1 month (1 month and 5 days, rounded down) + * * @param startDate The start date * @param endDate The end date - * @returns The number of months between the two dates + * @returns The number of complete months between the two dates */ export function getMonthsDifference(startDate: Date, endDate: Date): number { const years = endDate.getFullYear() - startDate.getFullYear(); const months = endDate.getMonth() - startDate.getMonth(); - return years * 12 + months; + const days = endDate.getDate() - startDate.getDate(); + + let totalMonths = years * 12 + months; + + // If the end day is before the start day, we haven't completed a full month + if (days < 0) { + totalMonths--; + } + + return Math.max(0, totalMonths); } From c41513faa9d9db3b660fce36e0d27c29bc471606 Mon Sep 17 00:00:00 2001 From: tamir Date: Thu, 26 Feb 2026 10:09:56 +0200 Subject: [PATCH 6/6] Removed service fee enabled updating --- .../solver/content-types/solver/lifecycles.ts | 89 ------------------- src/utils/date.ts | 33 ------- 2 files changed, 122 deletions(-) delete mode 100644 src/utils/date.ts diff --git a/src/api/solver/content-types/solver/lifecycles.ts b/src/api/solver/content-types/solver/lifecycles.ts index c23b5d4..4fb31ff 100644 --- a/src/api/solver/content-types/solver/lifecycles.ts +++ b/src/api/solver/content-types/solver/lifecycles.ts @@ -1,15 +1,9 @@ import { errors } from "@strapi/utils"; -import { getMonthsDifference } from "../../../../utils/date"; - -const COW_BONDING_POOL_SERVICE_FEE_TH: number = 6; -const COLOCATED_BONDING_POOL_SERVICE_FEE_TH: number = 3; -const COW_CONDING_POOL_NAME: string = "CoW"; export default { async afterCreate(event) { try { await updateActiveNetworks(event); - await updateServiceFeeEnabled(event); } catch (error) { console.error("Error in beforeCreate:", error); throw new errors.ValidationError(error.message || "Error processing solver data"); @@ -19,7 +13,6 @@ export default { async afterUpdate(event) { try { await updateActiveNetworks(event); - await updateServiceFeeEnabled(event); } catch (error) { console.error("Error in beforeUpdate:", error); throw new errors.ValidationError(error.message || "Error processing solver data"); @@ -113,85 +106,3 @@ async function updateActiveNetworksData(solver: Solver, data: SolverData): Promi data.hasActiveNetworks = activeNetworks.length > 0; data.activeNetworks = activeNetworks; } - -async function updateServiceFeeEnabled(event: StrapiEvent): Promise { - const { data, where } = event.params; - const solverData: SolverData = data; - - if (where) { - try { - const solver = await strapi.entityService.findOne( - 'api::solver.solver', - where.id, - { - populate: { - solver_bonding_pools: { - fields: ['name', 'joinedOn'] - } - } - } - ); - - if (solver) { - await setServiceFeeEnabled(solver as Solver, solverData); - } - } catch (error) { - console.error(`Error fetching solver data for service fee calculation (id ${where.id}):`, error); - throw new errors.ApplicationError(`Failed to fetch solver data for service fee calculation: ${error.message}`); - } - } - // For create operation, we handle it in afterCreate since we need the ID -} - -/** - * Determines if a solver is eligible for service fees based on bonding pool criteria. - * Pure function that checks eligibility based on time thresholds: - * - 6+ months for non-colocated CoW pools - * - 3+ months for colocated pools - * @param solver The solver entity to check - * @returns Boolean indicating if the solver is eligible for service fees - */ -function isEligibleForServiceFee(solver: Solver): boolean { - if (!solver.solver_bonding_pools || solver.solver_bonding_pools.length === 0) { - return false; - } - - const currentDate = new Date(); - - for (const bondingPool of solver.solver_bonding_pools) { - // Skip if joinedOn field is not set (not a mandatory field) - if (!bondingPool.joinedOn) { - continue; - } - - const joinedDate = new Date(bondingPool.joinedOn); - const monthsDifference = getMonthsDifference(joinedDate, currentDate); - - if (bondingPool.name === COW_CONDING_POOL_NAME && solver.isColocated === "No") { - if (monthsDifference >= COW_BONDING_POOL_SERVICE_FEE_TH) { - return true; - } - } - else if (solver.isColocated === "Yes") { - if (monthsDifference >= COLOCATED_BONDING_POOL_SERVICE_FEE_TH) { - return true; - } - } - // For partial colocated, we'll treat it as not colocated - } - - return false; -} - -/** - * Sets the isServiceFeeEnabled flag in the solver data based on eligibility. - * Uses the pure function isEligibleForServiceFee to determine eligibility. - */ -async function setServiceFeeEnabled(solver: Solver, data: SolverData): Promise { - try { - data.isServiceFeeEnabled = isEligibleForServiceFee(solver); - } catch (error) { - console.error(`Error setting service fee enabled status:`, error); - throw new errors.ApplicationError(`Failed to set service fee status: ${error.message}`); - } -} diff --git a/src/utils/date.ts b/src/utils/date.ts deleted file mode 100644 index a85e5c7..0000000 --- a/src/utils/date.ts +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Date utility functions - */ - -/** - * Calculate the actual number of months between two dates - * This function considers the full date (year, month, and day) to determine - * if a complete month has passed between the start and end dates. - * - * Examples: - * - 31/01/2026 to 01/02/2026 = 0 months (only 1 day difference) - * - 01/01/2026 to 02/01/2026 = 0 months (only 1 day difference) - * - 01/01/2026 to 01/02/2026 = 1 month (exactly 1 month) - * - 15/01/2026 to 20/02/2026 = 1 month (1 month and 5 days, rounded down) - * - * @param startDate The start date - * @param endDate The end date - * @returns The number of complete months between the two dates - */ -export function getMonthsDifference(startDate: Date, endDate: Date): number { - const years = endDate.getFullYear() - startDate.getFullYear(); - const months = endDate.getMonth() - startDate.getMonth(); - const days = endDate.getDate() - startDate.getDate(); - - let totalMonths = years * 12 + months; - - // If the end day is before the start day, we haven't completed a full month - if (days < 0) { - totalMonths--; - } - - return Math.max(0, totalMonths); -}