Skip to content

Commit

Permalink
feat: add poc
Browse files Browse the repository at this point in the history
  • Loading branch information
jahabeebs committed Sep 18, 2024
1 parent 52099de commit 75dc364
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 58 deletions.
71 changes: 67 additions & 4 deletions packages/automated-dispute/src/exceptions/errorFactory.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,80 @@
import { CustomContractError } from "../exceptions/index.js";
import { ErrorHandlingStrategy } from "../types/index.js";

const errorStrategies: Map<string, ErrorHandlingStrategy> = new Map([
//TODO: add all error strategies
const errorStrategiesEntries: [string, ErrorHandlingStrategy][] = [
[
"EBORequestCreator_InvalidEpoch",
"ValidatorLib_InvalidResponseBody",
{
shouldNotify: true,
shouldTerminate: true,
shouldConsume: false,
},
],
]);
[
"BondEscalationAccounting_InsufficientFunds",
{
shouldNotify: true,
shouldTerminate: false,
shouldConsume: false,
},
],
[
"BondEscalationAccounting_AlreadySettled",
{
shouldNotify: false,
shouldTerminate: false,
shouldConsume: true,
},
],
[
"BondEscalationModule_InvalidDispute",
{
shouldNotify: true,
shouldTerminate: false,
shouldConsume: true,
customAction: async (context) => {
context.registry.removeDispute(context.dispute.id);
},
},
],
[
"AccountingExtension_InsufficientFunds",
{
shouldNotify: true,
shouldTerminate: false,
shouldConsume: false,
},
],
[
"Oracle_InvalidDisputeId",
{
shouldNotify: true,
shouldTerminate: false,
shouldConsume: true,
customAction: async (context) => {
context.registry.removeDispute(context.dispute.id);
},
},
],
[
"Oracle_AlreadyFinalized",
{
shouldNotify: false,
shouldTerminate: false,
shouldConsume: true,
},
],
[
"EBORequestModule_InvalidRequester",
{
shouldNotify: true,
shouldTerminate: true,
shouldConsume: false,
},
],
];

const errorStrategies = new Map<string, ErrorHandlingStrategy>(errorStrategiesEntries);

export class ErrorFactory {
public static createError(errorName: string): CustomContractError {
Expand Down
153 changes: 99 additions & 54 deletions packages/automated-dispute/src/services/eboActor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -286,15 +286,27 @@ export class EboActor {
);
} catch (err) {
if (err instanceof ContractFunctionRevertedError) {
const customError = ErrorFactory.createError(err.name).setContext({
const errorName = err.data?.errorName || err.name;
this.logger.warn(`Finalize request failed due to: ${errorName}`);

const customError = ErrorFactory.createError(errorName).setContext({
request,
acceptedResponse,
registry: this.registry,
});

await ErrorHandler.handle(customError, {
//TODO: error logic
consumeEvent: () => {
this.logger.info(`Consuming error: ${customError.name}`);
},
terminateActor: () => {
throw customError;
},
});

if (customError.strategy.shouldTerminate) {
throw customError;
}
} else {
throw err;
}
Expand Down Expand Up @@ -375,50 +387,53 @@ export class EboActor {
* @param response the dispute's response
* @param dispute the dispute
*/
private settleDispute(request: Request, response: Response, dispute: Dispute): Promise<void> {
return Promise.resolve()
.then(async () => {
this.logger.info(`Settling dispute ${dispute.id}...`);

// OPTIMIZE: check for pledges to potentially save the ShouldBeEscalated error

await this.protocolProvider.settleDispute(
request.prophetData,
response.prophetData,
dispute.prophetData,
);

this.logger.info(`Dispute ${dispute.id} settled.`);
})
.catch(async (err) => {
this.logger.warn(`Dispute ${dispute.id} was not settled.`);
private async settleDispute(
request: Request,
response: Response,
dispute: Dispute,
): Promise<void> {
try {
this.logger.info(`Settling dispute ${dispute.id}...`);

// TODO: use custom errors to be developed while implementing ProtocolProvider
if (!(err instanceof ContractFunctionRevertedError)) throw err;
// OPTIMIZE: check for pledges to potentially save the ShouldBeEscalated error

this.logger.warn(`Call reverted for ${dispute.id} due to: ${err.data?.errorName}`);
await this.protocolProvider.settleDispute(
request.prophetData,
response.prophetData,
dispute.prophetData,
);

if (err.data?.errorName === "BondEscalationModule_ShouldBeEscalated") {
this.logger.warn(`Escalating dispute ${dispute.id}...`);
this.logger.info(`Dispute ${dispute.id} settled.`);
} catch (err) {
if (err instanceof ContractFunctionRevertedError) {
const errorName = err.data?.errorName || err.name;
this.logger.warn(`Call reverted for dispute ${dispute.id} due to: ${errorName}`);

await this.protocolProvider.escalateDispute(
request.prophetData,
response.prophetData,
dispute.prophetData,
);
const customError = ErrorFactory.createError(errorName).setContext({
request,
response,
dispute,
registry: this.registry,
});

// TODO: notify
await ErrorHandler.handle(customError, {
consumeEvent: () => {
// TODO: consume
this.logger.info(`Consuming error: ${customError.name}`);
},
terminateActor: () => {
// Rethrow to allow EboProcessor to handle termination
throw customError;
},
});

this.logger.warn(`Dispute ${dispute.id} was escalated.`);
if (customError.strategy.shouldTerminate) {
throw customError;
}
})
.catch((err) => {
this.logger.error(`Failed to escalate dispute ${dispute.id}.`);

// TODO: notify

} else {
throw err;
});
}
}
}

/**
Expand Down Expand Up @@ -771,24 +786,38 @@ export class EboActor {
*/
private async pledgeFor(request: Request, dispute: Dispute) {
try {
this.logger.info(`Pledging against dispute ${dispute.id}`);
this.logger.info(`Pledging for dispute ${dispute.id}`);

await this.protocolProvider.pledgeForDispute(request.prophetData, dispute.prophetData);
} catch (err) {
if (err instanceof ContractFunctionRevertedError) {
// TODO: handle each error appropriately
this.logger.warn(`Pledging for dispute ${dispute.id} was reverted. Skipping...`);
} else {
// TODO: handle each error appropriately
this.logger.error(
`Actor handling request ${this.actorRequest.id} is not able to continue.`,
);
const errorName = err.data?.errorName || err.name;
this.logger.warn(`Pledge for dispute ${dispute.id} reverted due to: ${errorName}`);

const customError = ErrorFactory.createError(errorName).setContext({
request,
dispute,
registry: this.registry,
});

await ErrorHandler.handle(customError, {
consumeEvent: () => {
// TODO: consume error
this.logger.info(`Consuming error: ${customError.name}`);
},
terminateActor: () => {
throw customError;
},
});

if (customError.strategy.shouldTerminate) {
throw customError;
}
} else {
throw err;
}
}
}

/**
* Pledge against the dispute.
*
Expand All @@ -797,22 +826,38 @@ export class EboActor {
*/
private async pledgeAgainst(request: Request, dispute: Dispute) {
try {
this.logger.info(`Pledging for dispute ${dispute.id}`);
this.logger.info(`Pledging against dispute ${dispute.id}`);

await this.protocolProvider.pledgeAgainstDispute(
request.prophetData,
dispute.prophetData,
);
} catch (err) {
if (err instanceof ContractFunctionRevertedError) {
// TODO: handle each error appropriately
this.logger.warn(`Pledging on dispute ${dispute.id} was reverted. Skipping...`);
} else {
// TODO: handle each error appropriately
this.logger.error(
`Actor handling request ${this.actorRequest.id} is not able to continue.`,
const errorName = err.data?.errorName || err.name;
this.logger.warn(
`Pledge against dispute ${dispute.id} reverted due to: ${errorName}`,
);

const customError = ErrorFactory.createError(errorName).setContext({
request,
dispute,
registry: this.registry,
});

await ErrorHandler.handle(customError, {
consumeEvent: () => {
this.logger.info(`Consuming error: ${customError.name}`);
},
terminateActor: () => {
throw customError;
},
});

if (customError.strategy.shouldTerminate) {
throw customError;
}
} else {
throw err;
}
}
Expand Down

0 comments on commit 75dc364

Please sign in to comment.