diff --git a/src/commands/client.ts b/src/commands/client.ts index 7e81938..7bb43ce 100644 --- a/src/commands/client.ts +++ b/src/commands/client.ts @@ -545,11 +545,25 @@ export function registerClientCommands(program: Command): void { ]); const txnHash = Array.isArray(result) ? result[0] : result; - const message = await agentApi.confirmJobFeedback( - chainId, - opts.jobId, - txnHash - ); + let message: string | undefined; + try { + message = await agentApi.confirmJobFeedback( + chainId, + opts.jobId, + txnHash + ); + } catch (err) { + const errMessage = err instanceof Error ? err.message : String(err); + throw new CliError( + `Backend confirmation failed after review transaction was broadcast. Tx hash: ${txnHash}. ${errMessage}`, + "API_ERROR", + "The on-chain transaction was already sent. Keep the Tx Hash and retry or contact support with it.", + { + action: "client review", + txnHash, + } + ); + } if (json) { outputResult(json, { diff --git a/src/commands/compute.ts b/src/commands/compute.ts index 306f7d6..65b0cd0 100644 --- a/src/commands/compute.ts +++ b/src/commands/compute.ts @@ -126,12 +126,20 @@ export function registerComputeCommands(program: Command): void { }); const agentAddress = getWalletAddress(); - const result = await agentApi.computeTopUp( - agentId, - agentAddress, - amount, - txnHash - ); + try { + await agentApi.computeTopUp(agentId, agentAddress, amount, txnHash); + } catch (err) { + const message = err instanceof Error ? err.message : String(err); + throw new CliError( + `Backend confirmation failed after compute top-up transaction was broadcast. Tx hash: ${txnHash}. ${message}`, + "API_ERROR", + "The on-chain transaction was already sent. Keep the Tx Hash and retry or contact support with it.", + { + action: "compute top-up", + txnHash, + } + ); + } if (json) { outputResult(json, { diff --git a/src/lib/errors.ts b/src/lib/errors.ts index a1797ba..e7b1e27 100644 --- a/src/lib/errors.ts +++ b/src/lib/errors.ts @@ -15,10 +15,17 @@ export type ErrorCode = export class CliError extends Error { code: ErrorCode; recovery?: string; + details?: Record; - constructor(message: string, code: ErrorCode, recovery?: string) { + constructor( + message: string, + code: ErrorCode, + recovery?: string, + details?: Record + ) { super(message); this.code = code; this.recovery = recovery; + this.details = details; } } diff --git a/src/lib/output.ts b/src/lib/output.ts index bb5dfd9..16c4034 100644 --- a/src/lib/output.ts +++ b/src/lib/output.ts @@ -39,6 +39,11 @@ export function outputError( if (isCliErr) { payload.code = errOrMessage.code; if (errOrMessage.recovery) payload.recovery = errOrMessage.recovery; + if (errOrMessage.details) { + for (const [key, value] of Object.entries(errOrMessage.details)) { + payload[key] = String(value); + } + } } process.stdout.write(JSON.stringify(payload) + "\n"); } else {