From e7b495527c2a29131853e6482a8ae583488e8cba Mon Sep 17 00:00:00 2001 From: flopez7 Date: Fri, 24 Apr 2026 14:47:47 +0200 Subject: [PATCH 1/3] mark escrow completion as completed before webhook creation --- .../escrow-completion.service.spec.ts | 11 ++--- .../escrow-completion.service.ts | 46 ++++++++----------- 2 files changed, 22 insertions(+), 35 deletions(-) diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts index d8a951f98f..463ef8be39 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts @@ -958,8 +958,7 @@ describe('EscrowCompletionService', () => { ); expect(mockEscrowCompletionRepository.updateOne).toHaveBeenCalledWith({ ...paidPayoutsRecord, - failureDetail: 'Error message: Webhook url is no set for oracle', - status: 'failed', + status: 'completed', }); }); @@ -988,10 +987,7 @@ describe('EscrowCompletionService', () => { ); expect(mockEscrowCompletionRepository.updateOne).toHaveBeenCalledWith({ ...paidPayoutsRecord, - failureDetail: expect.stringContaining( - 'Failed to create outgoing webhook for oracle. Address: 0x', - ), - status: 'failed', + status: 'completed', }); }); }); @@ -1177,8 +1173,7 @@ describe('EscrowCompletionService', () => { expect(mockEscrowCompletionRepository.updateOne).toHaveBeenCalledTimes(1); expect(mockEscrowCompletionRepository.updateOne).toHaveBeenCalledWith({ ...paidPayoutsRecord, - failureDetail: 'Error message: Oracle data is missing', - status: 'failed', + status: 'completed', }); }); }); diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts index cf119c2515..25e608ed17 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts @@ -268,6 +268,9 @@ export class EscrowCompletionService { ); } + escrowCompletionEntity.status = EscrowCompletionStatus.COMPLETED; + await this.escrowCompletionRepository.updateOne(escrowCompletionEntity); + const oracleAddresses: string[] = [ escrowData.launcher as string, escrowData.exchangeOracle as string, @@ -282,19 +285,26 @@ export class EscrowCompletionService { : OutgoingWebhookEventType.ESCROW_COMPLETED, }; - let allWebhooksCreated = true; for (const oracleAddress of oracleAddresses) { const oracleData = await OperatorUtils.getOperator( chainId, oracleAddress, ); if (!oracleData) { - throw new Error('Oracle data is missing'); + this.logger.error('Oracle data is missing', { + escrowCompletionEntityId: escrowCompletionEntity.id, + oracleAddress, + }); + continue; } const { webhookUrl } = oracleData; if (!webhookUrl) { - throw new Error('Webhook url is no set for oracle'); + this.logger.error('Webhook url is no set for oracle', { + escrowCompletionEntityId: escrowCompletionEntity.id, + oracleAddress, + }); + continue; } try { @@ -308,32 +318,14 @@ export class EscrowCompletionService { * Already created. Noop. */ continue; - } else { - this.logger.error( - 'Failed to create outgoing webhook for oracle', - { - error, - escrowCompletionEntityId: escrowCompletionEntity.id, - oracleAddress, - }, - ); - - await this.handleEscrowCompletionError( - escrowCompletionEntity, - `Failed to create outgoing webhook for oracle. Address: ${oracleAddress}.`, - ); - allWebhooksCreated = false; - break; } - } - } - // Only set the status to COMPLETED if all webhooks were created successfully - if (allWebhooksCreated) { - escrowCompletionEntity.status = EscrowCompletionStatus.COMPLETED; - await this.escrowCompletionRepository.updateOne( - escrowCompletionEntity, - ); + this.logger.error('Failed to create outgoing webhook for oracle', { + error, + escrowCompletionEntityId: escrowCompletionEntity.id, + oracleAddress, + }); + } } } catch (error) { this.logger.error('Failed to process paid escrow completion', { From cde4bd8c8f2b4c01dfe50b7ded15114f125ab1e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Francisco=20L=C3=B3pez?= <50665615+flopez7@users.noreply.github.com> Date: Wed, 29 Apr 2026 09:43:48 +0200 Subject: [PATCH 2/3] Apply suggestion from @portuu3 Co-authored-by: portuu3 <61605646+portuu3@users.noreply.github.com> --- .../src/modules/escrow-completion/escrow-completion.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts index 25e608ed17..c2d41a6228 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts @@ -300,7 +300,7 @@ export class EscrowCompletionService { const { webhookUrl } = oracleData; if (!webhookUrl) { - this.logger.error('Webhook url is no set for oracle', { + this.logger.error('Webhook url is not set for this oracle', { escrowCompletionEntityId: escrowCompletionEntity.id, oracleAddress, }); From 9593ffb165433bbe5ea54189d0e3e5f89b84b34f Mon Sep 17 00:00:00 2001 From: flopez7 Date: Mon, 4 May 2026 11:01:01 +0200 Subject: [PATCH 3/3] Refactor escrow completion logic to skip webhook creation if oracle doesn't have webhook url --- .../escrow-completion.service.spec.ts | 8 +++- .../escrow-completion.service.ts | 40 ++++++++++++------- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts index 463ef8be39..a912424054 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.spec.ts @@ -987,7 +987,10 @@ describe('EscrowCompletionService', () => { ); expect(mockEscrowCompletionRepository.updateOne).toHaveBeenCalledWith({ ...paidPayoutsRecord, - status: 'completed', + failureDetail: expect.stringContaining( + 'Failed to create outgoing webhook for oracle. Address: 0x', + ), + status: 'failed', }); }); }); @@ -1173,7 +1176,8 @@ describe('EscrowCompletionService', () => { expect(mockEscrowCompletionRepository.updateOne).toHaveBeenCalledTimes(1); expect(mockEscrowCompletionRepository.updateOne).toHaveBeenCalledWith({ ...paidPayoutsRecord, - status: 'completed', + failureDetail: 'Error message: Oracle data is missing', + status: 'failed', }); }); }); diff --git a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts index c2d41a6228..8dbc5731f6 100644 --- a/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts +++ b/packages/apps/reputation-oracle/server/src/modules/escrow-completion/escrow-completion.service.ts @@ -268,9 +268,6 @@ export class EscrowCompletionService { ); } - escrowCompletionEntity.status = EscrowCompletionStatus.COMPLETED; - await this.escrowCompletionRepository.updateOne(escrowCompletionEntity); - const oracleAddresses: string[] = [ escrowData.launcher as string, escrowData.exchangeOracle as string, @@ -285,17 +282,14 @@ export class EscrowCompletionService { : OutgoingWebhookEventType.ESCROW_COMPLETED, }; + let allWebhooksCreated = true; for (const oracleAddress of oracleAddresses) { const oracleData = await OperatorUtils.getOperator( chainId, oracleAddress, ); if (!oracleData) { - this.logger.error('Oracle data is missing', { - escrowCompletionEntityId: escrowCompletionEntity.id, - oracleAddress, - }); - continue; + throw new Error('Oracle data is missing'); } const { webhookUrl } = oracleData; @@ -318,15 +312,33 @@ export class EscrowCompletionService { * Already created. Noop. */ continue; + } else { + this.logger.error( + 'Failed to create outgoing webhook for oracle', + { + error, + escrowCompletionEntityId: escrowCompletionEntity.id, + oracleAddress, + }, + ); + + await this.handleEscrowCompletionError( + escrowCompletionEntity, + `Failed to create outgoing webhook for oracle. Address: ${oracleAddress}.`, + ); + allWebhooksCreated = false; + break; } - - this.logger.error('Failed to create outgoing webhook for oracle', { - error, - escrowCompletionEntityId: escrowCompletionEntity.id, - oracleAddress, - }); } } + + // Only set the status to COMPLETED if all webhooks were created successfully + if (allWebhooksCreated) { + escrowCompletionEntity.status = EscrowCompletionStatus.COMPLETED; + await this.escrowCompletionRepository.updateOne( + escrowCompletionEntity, + ); + } } catch (error) { this.logger.error('Failed to process paid escrow completion', { error,