Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions database/migrations/schema-changes-migration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
async function up(knex) {
// 1. Update Solver Bonding Pool: rename bonding_pool to name
// First, get all solver bonding pools with their bonding_pool relation
const solverBondingPools = await knex('solver_bonding_pools')
.select('id', 'bonding_pool_id')
.whereNotNull('bonding_pool_id');

// For each solver bonding pool, get the name from bonding_pool and update the solver bonding pool
for (const sbp of solverBondingPools) {
if (sbp.bonding_pool_id) {
// Get the name from bonding_pool
const bondingPool = await knex('bonding_pools')
.select('name')
.where('id', sbp.bonding_pool_id)
.first();

if (bondingPool && bondingPool.name) {
// Update the solver bonding pool with the name
await knex('solver_bonding_pools')
.where('id', sbp.id)
.update({
name: bondingPool.name
});
}
}
}

// 2. Calculate activeNetworks for all solvers
const solvers = await knex('solvers').select('id');

for (const solver of solvers) {
// Get all active networks for this solver
const activeNetworks = await knex('solver_networks')
.join('networks', 'solver_networks.network_id', 'networks.id')
.where({
'solver_networks.solver_id': solver.id,
'solver_networks.active': true
})
.select('networks.name');

// Extract network names
const networkNames = activeNetworks.map(n => n.name);

// Update the solver with activeNetworks and hasActiveNetworks
await knex('solvers')
.where('id', solver.id)
.update({
activeNetworks: JSON.stringify(networkNames),
hasActiveNetworks: networkNames.length > 0
});
}

// 3. Ensure all required fields are set for Solver Network
// Make a list of solver networks that have isVouched=true but no vouchedBy
const vouchedNetworks = await knex('solver_networks')
.where('isVouched', true)
.whereNull('vouchedBy');

console.log(`Found ${vouchedNetworks.length} solver networks with isVouched=true but no vouchedBy`);

return;
}

async function down(knex) {
// This migration cannot be reversed automatically
console.log('This migration cannot be reversed automatically');
return;
}

module.exports = { up, down };
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { updateServiceFeeEnabledForSolver } from '../../../solver/content-types/solver/lifecycles';

export default {
async afterCreate(event) {
await updateRelatedSolvers(event);
},

async afterUpdate(event) {
await updateRelatedSolvers(event);
},

async beforeDelete(event) {
await storeRelatedSolversForUpdate(event);
},

async afterDelete(event) {
await updateStoredSolvers(event);
},
};

// Store for temporarily keeping solver IDs between beforeDelete and afterDelete
const solverIdsToUpdate = new Map();

async function updateRelatedSolvers(event) {
try {
const { result } = event;

// If this is a delete operation, result might not be available
if (!result || !result.solvers) {
return;
}

// Get the solver IDs
const solverIds = Array.isArray(result.solvers)
? result.solvers.map(solver => solver.id || solver)
: [];

// If no solvers are directly available in the result, fetch them
if (solverIds.length === 0 && result.id) {
const bondingPool = await strapi.entityService.findOne(
'api::solver-bonding-pool.solver-bonding-pool',
result.id,
{ populate: ['solvers'] }
);

if (bondingPool && bondingPool.solvers) {
bondingPool.solvers.forEach(solver => {
solverIds.push(solver.id);
});
}
}

// Update each solver's service fee enabled status
for (const solverId of solverIds) {
if (solverId) {
await updateServiceFeeEnabledForSolver(solverId);
}
}
} catch (error) {
console.error('Error updating related solvers:', error);
}
}

async function storeRelatedSolversForUpdate(event) {
try {
const { where } = event.params;
const { id } = where;

// Get the bonding pool with its solvers
const bondingPool = await strapi.entityService.findOne(
'api::solver-bonding-pool.solver-bonding-pool',
id,
{ populate: ['solvers'] }
);

if (bondingPool && bondingPool.solvers) {
// Store the solver IDs for later use in afterDelete
const solverIds = bondingPool.solvers.map(solver => solver.id);
solverIdsToUpdate.set(id, solverIds);
}
} catch (error) {
console.error('Error storing related solvers for update:', error);
}
}

async function updateStoredSolvers(event) {
try {
const { where } = event.params;
const { id } = where;

// Get the stored solver IDs
const solverIds = solverIdsToUpdate.get(id) || [];

// Update each solver's service fee enabled status
for (const solverId of solverIds) {
if (solverId) {
await updateServiceFeeEnabledForSolver(solverId);
}
}

// Clean up the stored solver IDs
solverIdsToUpdate.delete(id);
} catch (error) {
console.error('Error updating stored solvers:', error);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@
"type": "datetime",
"required": true
},
"bonding_pool": {
"type": "relation",
"relation": "manyToOne",
"target": "api::bonding-pool.bonding-pool",
"inversedBy": "solver_bonding_pools"
"name": {
"type": "string",
"required": true
},
"solvers": {
"type": "relation",
Expand All @@ -37,6 +35,12 @@
"type": "boolean",
"required": true,
"default": false
},
"solver_networks": {
"type": "relation",
"relation": "oneToMany",
"target": "api::solver-network.solver-network",
"mappedBy": "vouchedBy"
}
}
}
53 changes: 53 additions & 0 deletions src/api/solver-network/content-types/solver-network/lifecycles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { calculateActiveNetworksForSolver } from '../../../solver/content-types/solver/lifecycles';

export default {
async beforeCreate(event) {
await validateVouchedBy(event);
},

async beforeUpdate(event) {
await validateVouchedBy(event);
},

async afterCreate(event) {
await updateParentSolver(event);
},

async afterUpdate(event) {
await updateParentSolver(event);
},

async afterDelete(event) {
await updateParentSolver(event);
},
};

async function validateVouchedBy(event) {
const { data } = event.params;

// Check if isVouched is true and vouchedBy is not set
if (data.isVouched === true && !data.vouchedBy) {
throw new Error('vouchedBy relationship must be set when isVouched is true');
}
}

async function updateParentSolver(event) {
try {
const { result } = event;

// If this is a delete operation, result might not be available
if (!result || !result.solver) {
return;
}

// Get the solver ID
const solverId = result.solver.id || result.solver;

if (solverId) {
// Update the solver's activeNetworks field
await calculateActiveNetworksForSolver(solverId);
}
} catch (error) {
console.error('Error updating parent solver:', error);
}
}
14 changes: 11 additions & 3 deletions src/api/solver-network/content-types/solver-network/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@
"type": "relation",
"relation": "manyToOne",
"target": "api::network.network",
"inversedBy": "solver_networks"
"inversedBy": "solver_networks",
"required": true
},
"address": {
"type": "string",
"regex": "^(0x)?[0-9a-fA-F]{40}$"
"regex": "^(0x)?[0-9a-fA-F]{40}$",
"required": true
},
"payoutAddress": {
"type": "string",
Expand All @@ -40,7 +42,8 @@
"environment": {
"type": "relation",
"relation": "oneToOne",
"target": "api::environment.environment"
"target": "api::environment.environment",
"required": true
},
"isWhiteListed": {
"type": "boolean",
Expand All @@ -54,6 +57,11 @@
"type": "boolean",
"default": false,
"required": true
},
"vouchedBy": {
"type": "relation",
"relation": "manyToOne",
"target": "api::solver-bonding-pool.solver-bonding-pool"
}
}
}
Loading
Loading