UNPKG

@openocean.finance/widget-sdk

Version:

OpenOcean Any-to-Any Cross-Chain-Swap SDK

189 lines 7.18 kB
import { executionState } from './executionState.js'; import { getProcessMessage } from './processMessages.js'; /** * Manages status updates of a route and provides various functions for tracking processes * @param {string} routeId The route dd this StatusManger belongs to. * @returns {StatusManager} An instance of StatusManager. */ export class StatusManager { routeId; shouldUpdate = true; constructor(routeId) { this.routeId = routeId; } /** * Initializes the execution object of a Step. * @param step The current step in execution * @returns The initialized execution object for this step and a function to update this step */ initExecutionObject = (step) => { if (!step.execution) { step.execution = { status: 'PENDING', process: [], startedAt: Date.now(), }; this.updateStepInRoute(step); } // Change status to PENDING after resuming from FAILED if (step.execution.status === 'FAILED') { step.execution.startedAt = Date.now(); step.execution.status = 'PENDING'; this.updateStepInRoute(step); } return step.execution; }; /** * Updates the execution object of a Step. * @param step The current step in execution * @param status The status for the execution * @param execution Optional. Information about received tokens * @returns The step with the updated execution object */ updateExecution(step, status, execution) { if (!step.execution) { throw Error("Can't update empty execution."); } step.execution.status = status; if (status === 'DONE') { step.execution.doneAt = Date.now(); } if (execution) { step.execution = { ...step.execution, ...execution, }; } this.updateStepInRoute(step); return step; } /** * Finds a process of the specified type in the step's execution * @param step The step to search in * @param type The process type to find * @param status Optional status to update the process with if found * @returns The found process or undefined if not found */ findProcess(step, type, status) { if (!step.execution?.process) { throw new Error("Execution hasn't been initialized."); } const process = step.execution.process.find((p) => p.type === type); if (process && status && process.status !== status) { process.status = status; this.updateStepInRoute(step); } return process; } /** * Create and push a new process into the execution. * @param step The step that should contain the new process. * @param type Type of the process. Used to identify already existing processes. * @param chainId Chain Id of the process. * @param status By default created procces is set to the STARTED status. We can override new process with the needed status. * @returns Returns process. */ findOrCreateProcess = ({ step, type, chainId, status, startedAt, }) => { const process = this.findProcess(step, type, status); if (process) { return process; } const newProcess = { type: type, startedAt: startedAt ?? Date.now(), message: getProcessMessage(type, status ?? 'STARTED'), status: status ?? 'STARTED', chainId: chainId, }; step.execution.process.push(newProcess); this.updateStepInRoute(step); return newProcess; }; /** * Update a process object. * @param step The step where the process should be updated * @param type The process type to update * @param status The status the process gets. * @param [params] Additional parameters to append to the process. * @returns The update process */ updateProcess = (step, type, status, params) => { if (!step.execution) { throw new Error("Can't update an empty step execution."); } const currentProcess = this.findProcess(step, type); if (!currentProcess) { throw new Error("Can't find a process for the given type."); } switch (status) { case 'CANCELLED': currentProcess.doneAt = Date.now(); break; case 'FAILED': currentProcess.doneAt = Date.now(); step.execution.status = 'FAILED'; break; case 'DONE': currentProcess.doneAt = Date.now(); break; case 'PENDING': step.execution.status = 'PENDING'; currentProcess.pendingAt = Date.now(); break; case 'ACTION_REQUIRED': step.execution.status = 'ACTION_REQUIRED'; currentProcess.actionRequiredAt = Date.now(); break; default: break; } currentProcess.status = status; currentProcess.message = getProcessMessage(type, status); // set extra parameters or overwritte the standard params set in the switch statement if (params) { for (const [key, value] of Object.entries(params)) { currentProcess[key] = value; } } // Sort processes, the ones with DONE status go first step.execution.process = [ ...step.execution.process.filter((process) => process.status === 'DONE'), ...step.execution.process.filter((process) => process.status !== 'DONE'), ]; this.updateStepInRoute(step); // updates the step in the route return currentProcess; }; /** * Remove a process from the execution * @param step The step where the process should be removed from * @param type The process type to remove */ removeProcess = (step, type) => { if (!step.execution) { throw new Error("Execution hasn't been initialized."); } const index = step.execution.process.findIndex((p) => p.type === type); step.execution.process.splice(index, 1); this.updateStepInRoute(step); }; updateStepInRoute = (step) => { if (!this.shouldUpdate) { return step; } const data = executionState.get(this.routeId); if (!data) { throw new Error('Execution data not found.'); } const stepIndex = data.route.steps.findIndex((routeStep) => routeStep.id === step.id); if (stepIndex === -1) { throw new Error("Couldn't find a step to update."); } data.route.steps[stepIndex] = { ...data.route.steps[stepIndex], ...step }; data.executionOptions?.updateRouteHook?.(data.route); return data.route.steps[stepIndex]; }; allowUpdates(value) { this.shouldUpdate = value; } } //# sourceMappingURL=StatusManager.js.map