UNPKG

@silvana-one/coordination

Version:

Silvana Coordination Client

232 lines 9.61 kB
import { Transaction } from "@mysten/sui/transactions"; import { SUI_CLOCK_OBJECT_ID } from "@mysten/sui/utils"; import { silvanaRegistryPackage } from "./package.js"; import { fetchSuiDynamicField, fetchSuiObject } from "./fetch.js"; export class AppInstanceManager { constructor(params) { this.registry = params.registry; } // Note: update_method and remove_method functions are not available in the Move module // These would need to be implemented in app_instance.move if needed createAppJob(params) { const { appInstance, description, method, sequences, data } = params; // Debug logging console.log("createAppJob params:", { appInstance, description, method, sequences, data: data instanceof Uint8Array ? `Uint8Array(${data.length})` : typeof data, dataContent: data instanceof Uint8Array ? Array.from(data) : data, }); const tx = new Transaction(); tx.moveCall({ target: `${silvanaRegistryPackage}::app_instance::create_app_job`, arguments: [ tx.object(appInstance), tx.pure.string(method), tx.pure.option("string", description ?? null), tx.pure.option("vector<u64>", sequences ?? null), tx.pure.vector("u8", data), tx.object(SUI_CLOCK_OBJECT_ID), ], }); return tx; } startAppJob(params) { const { appInstance, jobId } = params; const tx = new Transaction(); tx.moveCall({ target: `${silvanaRegistryPackage}::app_instance::start_app_job`, arguments: [ tx.object(appInstance), tx.pure.u64(jobId), tx.object(SUI_CLOCK_OBJECT_ID), ], }); return tx; } completeAppJob(params) { const { appInstance, jobId } = params; const tx = new Transaction(); tx.moveCall({ target: `${silvanaRegistryPackage}::app_instance::complete_app_job`, arguments: [ tx.object(appInstance), tx.pure.u64(jobId), tx.object(SUI_CLOCK_OBJECT_ID), ], }); return tx; } failAppJob(params) { const { appInstance, jobId, error } = params; const tx = new Transaction(); tx.moveCall({ target: `${silvanaRegistryPackage}::app_instance::fail_app_job`, arguments: [ tx.object(appInstance), tx.pure.u64(jobId), tx.pure.string(error), tx.object(SUI_CLOCK_OBJECT_ID), ], }); return tx; } async getAppInstance(appInstanceId) { try { const appInstance = await fetchSuiObject(appInstanceId); if (!appInstance) return undefined; const fields = appInstance?.data?.content?.fields; if (!fields) return undefined; // Parse methods from VecMap const methods = {}; const methodsArray = fields?.methods?.fields?.contents; if (Array.isArray(methodsArray)) { for (const entry of methodsArray) { const key = entry?.fields?.key; const value = entry?.fields?.value; if (key && value) { // Value might have a fields property too const methodFields = value.fields || value; methods[key] = { description: methodFields.description ?? undefined, developer: methodFields.developer, agent: methodFields.agent, agentMethod: methodFields.agent_method || methodFields.agentMethod, }; } } } // Parse metadata from VecMap const metadata = {}; const metadataArray = fields?.metadata?.fields?.contents; if (Array.isArray(metadataArray)) { for (const entry of metadataArray) { const key = entry?.fields?.key; const value = entry?.fields?.value; if (key && value) { metadata[key] = value; } } } // Parse kv from VecMap const kv = {}; const kvArray = fields?.kv?.fields?.contents; if (Array.isArray(kvArray)) { for (const entry of kvArray) { const key = entry?.fields?.key; const value = entry?.fields?.value; if (key && value) { kv[key] = value; } } } return { id: fields?.id?.id, silvanaAppName: fields.silvana_app_name, description: fields?.description ?? undefined, metadata, kv, methods, admin: fields.admin, sequence: Number(fields.sequence), blockNumber: Number(fields.block_number), previousBlockTimestamp: Number(fields.previous_block_timestamp), previousBlockLastSequence: Number(fields.previous_block_last_sequence), lastProvedBlockNumber: Number(fields.last_proved_block_number), lastSettledBlockNumber: Number(fields.last_settled_block_number), lastSettledSequence: Number(fields.last_settled_sequence), lastPurgedSequence: Number(fields.last_purged_sequence), isPaused: Boolean(fields.isPaused), minTimeBetweenBlocks: Number(fields.min_time_between_blocks), jobsId: String(fields.jobs?.fields?.id?.id ?? ""), createdAt: Number(fields.created_at), updatedAt: Number(fields.updated_at), }; } catch (error) { console.error("Error fetching app instance:", error); return undefined; } } async getAppJob(params) { try { const appInstanceObj = await fetchSuiObject(params.appInstance); if (!appInstanceObj) return undefined; // Jobs are embedded in the AppInstance - use correct path const jobsTableId = appInstanceObj?.data?.content?.fields?.jobs?.fields?.jobs?.fields?.id?.id; if (!jobsTableId) return undefined; const job = await fetchSuiDynamicField({ parentID: jobsTableId, fieldName: "jobs", type: "u64", key: String(params.jobId), }); if (!job) return undefined; const parseStatus = (status) => { // Check variant field format (used by Sui dynamic fields) if (status?.variant === "Pending") return { type: "Pending" }; if (status?.variant === "Running") return { type: "Running" }; if (status?.variant === "Failed") { // Get error from fields or from direct property const error = status?.fields?.error || status?.fields?.[0] || "Unknown error"; return { type: "Failed", error }; } // Legacy formats if (status?.Pending !== undefined) return { type: "Pending" }; if (status?.Running !== undefined) return { type: "Running" }; if (status?.Failed !== undefined) return { type: "Failed", error: status.Failed }; return { type: "Pending" }; }; return { id: job?.id?.id, jobId: Number(job.job_id), description: job?.description ?? undefined, developer: job.developer, agent: job.agent, agentMethod: job.agent_method, app: job.app, appInstance: job.app_instance, appInstanceMethod: job.app_instance_method, sequences: job?.sequences?.map((s) => Number(s)) ?? undefined, data: new Uint8Array(job.data), status: parseStatus(job.status), attempts: Number(job.attempts), createdAt: Number(job.created_at), updatedAt: Number(job.updated_at), }; } catch (error) { console.error("Error fetching app job:", error); return undefined; } } async getAppPendingJobs(appInstance) { try { const appInstanceObj = await fetchSuiObject(appInstance); if (!appInstanceObj) return []; // Jobs are embedded in the AppInstance - use correct path const pendingJobs = appInstanceObj?.data?.content?.fields?.jobs?.fields?.pending_jobs?.fields?.contents; if (!Array.isArray(pendingJobs)) return []; return pendingJobs.map((id) => Number(id)); } catch (error) { console.error("Error fetching app pending jobs:", error); return []; } } } //# sourceMappingURL=app_instance.js.map