kleros-escrow-data-service
Version:
Data service for interacting with Kleros Escrow
732 lines (731 loc) • 39.3 kB
JavaScript
import { ethers } from "ethers";
import { BaseService } from "../base/BaseService";
import { Party } from "../types/transaction";
/**
* Service for retrieving events from the Kleros Escrow contract
*/
export class EventService extends BaseService {
/**
* Creates a new EventService instance
* @param config The Kleros Escrow configuration
* @param provider Optional provider for read operations
*/
constructor(config, provider) {
super(config, provider);
}
/**
* Normalizes a block parameter to ensure it's in the correct format for ethers.js
* @param blockParam The block parameter (number, string, or undefined)
* @returns The normalized block parameter
*/
normalizeBlockParam(blockParam) {
if (blockParam === undefined) {
return undefined;
}
// Always convert to hex string
if (typeof blockParam === "string" && blockParam.startsWith("0x")) {
return blockParam;
}
const blockNumber = typeof blockParam === "string" ? parseInt(blockParam, 10) : blockParam;
if (isNaN(blockNumber)) {
console.warn(`Invalid block parameter: ${blockParam}, using undefined`);
return undefined;
}
// Always return as hex string
return ethers.utils.hexValue(blockNumber);
}
/**
* Gets all events for a specific transaction
* @param transactionId The ID of the transaction
* @param options Optional filter options including fromBlock and toBlock
* @returns All events related to the transaction
*/
async getEventsForTransaction(transactionId, options) {
try {
// Special case for known problematic transaction IDs
if (transactionId === "89") {
console.log("Using special handling for transaction ID 89");
// If no specific options provided, use extended search with no block range
if (!(options === null || options === void 0 ? void 0 : options.fromBlock) && !(options === null || options === void 0 ? void 0 : options.toBlock)) {
options = {}; // Ensure options is defined
}
}
// Normalize block parameters
let fromBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.fromBlock);
let toBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.toBlock);
// If toBlock is not provided, get the latest block
if (toBlock === undefined) {
try {
const latestBlock = await this.provider.getBlock("latest");
toBlock = ethers.utils.hexValue(latestBlock.number);
}
catch (error) {
console.warn("Error getting latest block, using a default range:", error);
// If we can't get the latest block, use 'latest'
toBlock = "latest";
}
}
console.log(`Searching for events from block ${fromBlock} to ${toBlock}`);
const events = [];
// Get all relevant event types with error handling
let metaEvidenceEvents = [];
let paymentEvents = [];
let hasToPayFeeEvents = [];
let disputeEvents = [];
let evidenceEvents = [];
let rulingEvents = [];
try {
// First try to get MetaEvidence events with the provided block range
metaEvidenceEvents = await this.getMetaEvidenceEvents(transactionId, {
fromBlock,
toBlock,
});
console.log(`Found ${metaEvidenceEvents.length} MetaEvidence events in initial search`);
// If no MetaEvidence events found and no specific block range was provided, try extended search
if (metaEvidenceEvents.length === 0 &&
!(options === null || options === void 0 ? void 0 : options.fromBlock) &&
!(options === null || options === void 0 ? void 0 : options.toBlock)) {
try {
console.log("No MetaEvidence events found in initial search. Starting extended search.");
metaEvidenceEvents =
await this.getMetaEvidenceEventsExtended(transactionId);
console.log(`Found ${metaEvidenceEvents.length} MetaEvidence events after extended search`);
// If we found events in extended search, update fromBlock and toBlock for other event types
if (metaEvidenceEvents.length > 0) {
// Find the earliest block where we found a MetaEvidence event
const earliestBlock = Math.min(...metaEvidenceEvents.map((e) => e.blockNumber));
// Update fromBlock to start from this block (or earlier)
if (earliestBlock > 0) {
fromBlock = ethers.utils.hexValue(Math.max(1, earliestBlock - 1000));
console.log(`Updating fromBlock to ${fromBlock} based on found MetaEvidence event`);
}
}
}
catch (error) {
console.warn("Error in extended MetaEvidence search:", error);
}
}
}
catch (error) {
console.warn("Error fetching MetaEvidence events:", error);
metaEvidenceEvents = [];
}
try {
paymentEvents = await this.getPaymentEvents(transactionId, {
fromBlock,
toBlock,
});
console.log(`Found ${paymentEvents.length} Payment events`);
}
catch (error) {
console.warn("Error fetching Payment events:", error);
paymentEvents = [];
}
try {
hasToPayFeeEvents = await this.getHasToPayFeeEvents(transactionId, {
fromBlock,
toBlock,
});
console.log(`Found ${hasToPayFeeEvents.length} HasToPayFee events`);
}
catch (error) {
console.warn("Error fetching HasToPayFee events:", error);
hasToPayFeeEvents = [];
}
try {
disputeEvents = await this.getDisputeEvents(transactionId, {
fromBlock,
toBlock,
});
console.log(`Found ${disputeEvents.length} Dispute events`);
}
catch (error) {
console.warn("Error fetching Dispute events:", error);
disputeEvents = [];
}
try {
evidenceEvents = await this.getEvidenceEvents(transactionId, {
fromBlock,
toBlock,
});
console.log(`Found ${evidenceEvents.length} Evidence events`);
}
catch (error) {
console.warn("Error fetching Evidence events:", error);
evidenceEvents = [];
}
try {
rulingEvents = await this.getRulingEvents(transactionId, {
fromBlock,
toBlock,
});
console.log(`Found ${rulingEvents.length} Ruling events`);
}
catch (error) {
console.warn("Error fetching Ruling events:", error);
rulingEvents = [];
}
// Ensure all event arrays are valid before combining
const allEvents = [
...(Array.isArray(metaEvidenceEvents) ? metaEvidenceEvents : []),
...(Array.isArray(paymentEvents) ? paymentEvents : []),
...(Array.isArray(hasToPayFeeEvents) ? hasToPayFeeEvents : []),
...(Array.isArray(disputeEvents) ? disputeEvents : []),
...(Array.isArray(evidenceEvents) ? evidenceEvents : []),
...(Array.isArray(rulingEvents) ? rulingEvents : []),
];
// Sort events by block number if they have one
return allEvents
.filter((event) => event && typeof event.blockNumber === "number")
.sort((a, b) => a.blockNumber - b.blockNumber);
}
catch (error) {
console.error("Error in getEventsForTransaction:", error);
return [];
}
}
/**
* Gets transaction creation events
* @param options Optional filter options including fromBlock and toBlock
* @returns An array of transaction creation events
*/
async getTransactionCreationEvents(options) {
try {
const fromBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.fromBlock);
const toBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.toBlock);
const filter = this.escrowContract.filters.TransactionCreated();
return await this.escrowContract.queryFilter(filter, fromBlock, toBlock);
}
catch (error) {
console.error("Error in getTransactionCreationEvents:", error);
return [];
}
}
/**
* Gets MetaEvidence events for a transaction with extended search capability
* @param transactionId The ID of the transaction
* @param options Optional filter options including fromBlock and toBlock
* @returns Array of MetaEvidence events
*/
async getMetaEvidenceEvents(transactionId, options) {
try {
const fromBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.fromBlock);
const toBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.toBlock);
console.log(`Getting MetaEvidence events with fromBlock=${fromBlock}, toBlock=${toBlock}`);
// Always use an unfiltered query and filter manually afterward
console.log(`Using unfiltered MetaEvidence query for ID: ${transactionId}`);
const filter = this.escrowContract.filters.MetaEvidence();
const events = await this.escrowContract.queryFilter(filter, fromBlock, toBlock);
// Filter the results manually to get only events for this transaction ID
const relevantEvents = events.filter((event) => {
var _a;
try {
const eventMetaEvidenceId = (_a = event.args) === null || _a === void 0 ? void 0 : _a._metaEvidenceID.toString();
return eventMetaEvidenceId === transactionId;
}
catch (error) {
console.warn(`Error comparing event metaEvidenceID:`, error);
return false;
}
});
console.log(`Found ${relevantEvents.length} MetaEvidence events for transaction ${transactionId}`);
// If we found events, process them and return
if (relevantEvents.length > 0) {
return await this.processMetaEvidenceEvents(relevantEvents, transactionId);
}
// If no events found and no specific block range was provided, try extended search
if (relevantEvents.length === 0 &&
!(options === null || options === void 0 ? void 0 : options.fromBlock) &&
!(options === null || options === void 0 ? void 0 : options.toBlock)) {
console.log(`No MetaEvidence events found in initial search. Starting extended search for transaction ${transactionId}`);
return await this.getMetaEvidenceEventsExtended(transactionId);
}
// If specific block range was provided but no events found, return empty array
return [];
}
catch (error) {
console.error("Error in getMetaEvidenceEvents:", error);
return []; // Return empty array instead of throwing to improve reliability
}
}
/**
* Extended search for MetaEvidence events
* Searches multiple block ranges until it finds at least one matching event
* @param transactionId The ID of the transaction
* @returns Array of MetaEvidence events
*/
async getMetaEvidenceEventsExtended(transactionId) {
try {
// Step 1: Get transaction details to find lastInteraction timestamp
console.log(`Getting transaction ${transactionId} details for extended search`);
const transaction = await this.escrowContract.transactions(transactionId);
const lastInteractionTimestamp = transaction.lastInteraction.toNumber();
console.log(`Transaction ${transactionId} lastInteraction timestamp: ${lastInteractionTimestamp}`);
// Step 2: Get current block and timestamp
const currentBlock = await this.provider.getBlockNumber();
const currentBlockDetails = await this.provider.getBlock(currentBlock);
const currentTimestamp = currentBlockDetails.timestamp;
// Step 3: Calculate approximate block for lastInteraction
const AVERAGE_BLOCK_TIME = 13; // seconds
const secondsDifference = currentTimestamp - lastInteractionTimestamp;
const estimatedBlocksBack = Math.floor(secondsDifference / AVERAGE_BLOCK_TIME);
const estimatedLastInteractionBlock = currentBlock - estimatedBlocksBack;
console.log(`Current block: ${currentBlock}, timestamp: ${currentTimestamp}`);
console.log(`Estimated blocks back: ${estimatedBlocksBack}`);
console.log(`Estimated block for lastInteraction: ${estimatedLastInteractionBlock}`);
// Step 4: Set initial search range (10,000 blocks before estimated block)
let fromBlock = Math.max(1, estimatedLastInteractionBlock - 10000);
let toBlock = estimatedLastInteractionBlock + 100; // Add small buffer
console.log(`Initial extended search range: ${fromBlock} to ${toBlock}`);
// Try initial range
let events = await this.searchMetaEvidenceInRange(transactionId, fromBlock, toBlock);
// If events found, return them
if (events.length > 0) {
console.log(`Found ${events.length} MetaEvidence events in initial extended search`);
return events;
}
// Step 5: If no events found, try up to 10 additional ranges of 10,000 blocks each
for (let i = 1; i <= 10; i++) {
const extendedFromBlock = Math.max(1, fromBlock - i * 10000);
const extendedToBlock = fromBlock - (i - 1) * 10000 - 1;
console.log(`Extended search ${i}: From block ${extendedFromBlock} to ${extendedToBlock}`);
events = await this.searchMetaEvidenceInRange(transactionId, extendedFromBlock, extendedToBlock);
// If events found, stop searching and return
if (events.length > 0) {
console.log(`Found ${events.length} MetaEvidence events in extended search ${i}`);
return events;
}
}
// If no events found after all attempts, return empty array
console.log(`No MetaEvidence events found after extended search for transaction ${transactionId}`);
return [];
}
catch (error) {
console.error("Error in getMetaEvidenceEventsExtended:", error);
return []; // Return empty array instead of throwing
}
}
/**
* Helper method to search for MetaEvidence events in a specific block range
* @param transactionId The ID of the transaction
* @param fromBlock The starting block number
* @param toBlock The ending block number
* @returns Array of MetaEvidence events
*/
async searchMetaEvidenceInRange(transactionId, fromBlock, toBlock) {
try {
// Convert block numbers to hex strings
const fromBlockHex = ethers.utils.hexValue(fromBlock);
const toBlockHex = ethers.utils.hexValue(toBlock);
console.log(`Searching for MetaEvidence events in range: ${fromBlock} to ${toBlock}`);
// Use unfiltered query
const filter = this.escrowContract.filters.MetaEvidence();
const events = await this.escrowContract.queryFilter(filter, fromBlockHex, toBlockHex);
// Filter manually for this transaction ID
const relevantEvents = events.filter((event) => {
var _a;
try {
const eventMetaEvidenceId = (_a = event.args) === null || _a === void 0 ? void 0 : _a._metaEvidenceID.toString();
return eventMetaEvidenceId === transactionId;
}
catch (error) {
return false;
}
});
console.log(`Found ${relevantEvents.length} matching events in range ${fromBlock} to ${toBlock}`);
// Process events if any found
if (relevantEvents.length > 0) {
return await this.processMetaEvidenceEvents(relevantEvents, transactionId);
}
return [];
}
catch (error) {
console.warn(`Error searching MetaEvidence in range ${fromBlock}-${toBlock}:`, error);
return []; // Return empty array instead of throwing
}
}
/**
* Process raw MetaEvidence events into structured format
* @param events Raw ethers.js events
* @param transactionId The transaction ID
* @returns Processed MetaEvidence events
*/
async processMetaEvidenceEvents(events, transactionId) {
var _a, _b, _c, _d;
const results = [];
for (const event of events) {
try {
const block = await event.getBlock();
results.push({
transactionId,
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: block.timestamp,
metaEvidenceId: (_a = event.args) === null || _a === void 0 ? void 0 : _a._metaEvidenceID.toString(),
evidence: (_b = event.args) === null || _b === void 0 ? void 0 : _b._evidence,
});
}
catch (error) {
console.warn(`Error processing MetaEvidence event at block ${event.blockNumber}:`, error);
// Add with minimal information
results.push({
transactionId,
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: 0, // Unknown timestamp
metaEvidenceId: (_c = event.args) === null || _c === void 0 ? void 0 : _c._metaEvidenceID.toString(),
evidence: (_d = event.args) === null || _d === void 0 ? void 0 : _d._evidence,
});
}
}
return results;
}
/**
* Gets payment events
* @param transactionId The ID of the transaction
* @param options Optional filter options including fromBlock and toBlock
* @returns An array of payment events
*/
async getPaymentEvents(transactionId, options) {
var _a, _b, _c, _d, _e, _f;
try {
const fromBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.fromBlock);
const toBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.toBlock);
console.log(`Getting Payment events with fromBlock=${fromBlock}, toBlock=${toBlock}`);
// Always use an unfiltered query and filter manually afterward
console.log(`Using unfiltered Payment query for ID: ${transactionId || "all"}`);
const filter = this.escrowContract.filters.Payment();
const events = await this.escrowContract.queryFilter(filter, fromBlock, toBlock);
// Filter the results manually to get only events for this transaction ID
const relevantEvents = transactionId
? events.filter((event) => {
var _a;
try {
const eventTransactionId = (_a = event.args) === null || _a === void 0 ? void 0 : _a._transactionID.toString();
return eventTransactionId === transactionId;
}
catch (error) {
console.warn(`Error comparing event transactionID:`, error);
return false;
}
})
: events;
console.log(`Found ${relevantEvents.length} Payment events for transaction ${transactionId || "all"}`);
const results = [];
for (const event of relevantEvents) {
try {
const block = await event.getBlock();
results.push({
transactionId: (_a = event.args) === null || _a === void 0 ? void 0 : _a._transactionID.toString(),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: block.timestamp,
amount: (_b = event.args) === null || _b === void 0 ? void 0 : _b._amount.toString(),
party: (_c = event.args) === null || _c === void 0 ? void 0 : _c._party,
});
}
catch (error) {
console.warn(`Error processing Payment event at block ${event.blockNumber}:`, error);
// Add the event with minimal information
results.push({
transactionId: (_d = event.args) === null || _d === void 0 ? void 0 : _d._transactionID.toString(),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: 0, // Unknown timestamp
amount: (_e = event.args) === null || _e === void 0 ? void 0 : _e._amount.toString(),
party: (_f = event.args) === null || _f === void 0 ? void 0 : _f._party,
});
}
}
return results;
}
catch (error) {
console.error("Error in getPaymentEvents:", error);
return []; // Return empty array instead of throwing
}
}
/**
* Gets HasToPayFee events for a transaction
* @param transactionId The ID of the transaction
* @param options Optional filter options including fromBlock and toBlock
* @returns Array of HasToPayFee events
*/
async getHasToPayFeeEvents(transactionId, options) {
var _a, _b, _c, _d;
try {
const fromBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.fromBlock);
const toBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.toBlock);
console.log(`Getting HasToPayFee events with fromBlock=${fromBlock}, toBlock=${toBlock}`);
// Always use an unfiltered query and filter manually afterward
console.log(`Using unfiltered HasToPayFee query for ID: ${transactionId || "all"}`);
const filter = this.escrowContract.filters.HasToPayFee();
const events = await this.escrowContract.queryFilter(filter, fromBlock, toBlock);
// Filter the results manually to get only events for this transaction ID
const relevantEvents = transactionId
? events.filter((event) => {
var _a;
try {
const eventTransactionId = (_a = event.args) === null || _a === void 0 ? void 0 : _a._transactionID.toString();
return eventTransactionId === transactionId;
}
catch (error) {
console.warn(`Error comparing event transactionID:`, error);
return false;
}
})
: events;
console.log(`Found ${relevantEvents.length} HasToPayFee events for transaction ${transactionId || "all"}`);
const results = [];
for (const event of relevantEvents) {
try {
const block = await event.getBlock();
results.push({
transactionId: (_a = event.args) === null || _a === void 0 ? void 0 : _a._transactionID.toString(),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: block.timestamp,
party: ((_b = event.args) === null || _b === void 0 ? void 0 : _b._party) === 0 ? Party.Sender : Party.Receiver,
});
}
catch (error) {
console.warn(`Error processing HasToPayFee event at block ${event.blockNumber}:`, error);
// Add the event with minimal information
results.push({
transactionId: (_c = event.args) === null || _c === void 0 ? void 0 : _c._transactionID.toString(),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: 0, // Unknown timestamp
party: ((_d = event.args) === null || _d === void 0 ? void 0 : _d._party) === 0 ? Party.Sender : Party.Receiver,
});
}
}
return results;
}
catch (error) {
console.error("Error in getHasToPayFeeEvents:", error);
return []; // Return empty array instead of throwing
}
}
/**
* Gets dispute creation events
* @param transactionId The ID of the transaction
* @param options Optional filter options including fromBlock and toBlock
* @returns An array of dispute creation events
*/
async getDisputeEvents(transactionId, options) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
try {
const fromBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.fromBlock);
const toBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.toBlock);
console.log(`Getting Dispute events with fromBlock=${fromBlock}, toBlock=${toBlock}`);
// Always use an unfiltered query and filter manually afterward
console.log(`Using unfiltered Dispute query for ID: ${transactionId || "all"}`);
const filter = this.escrowContract.filters.Dispute();
const events = await this.escrowContract.queryFilter(filter, fromBlock, toBlock);
// If transactionId is provided, filter events by metaEvidenceID
const relevantEvents = transactionId
? events.filter((event) => {
var _a;
try {
const eventMetaEvidenceId = (_a = event.args) === null || _a === void 0 ? void 0 : _a._metaEvidenceID.toString();
return eventMetaEvidenceId === transactionId;
}
catch (error) {
console.warn(`Error comparing event metaEvidenceID:`, error);
return false;
}
})
: events;
console.log(`Found ${relevantEvents.length} Dispute events for transaction ${transactionId || "all"}`);
const results = [];
for (const event of relevantEvents) {
try {
const block = await event.getBlock();
results.push({
transactionId: (_a = event.args) === null || _a === void 0 ? void 0 : _a._metaEvidenceID.toString(),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: block.timestamp,
disputeId: (_b = event.args) === null || _b === void 0 ? void 0 : _b._disputeID.toNumber(),
arbitrator: (_c = event.args) === null || _c === void 0 ? void 0 : _c._arbitrator,
metaEvidenceId: (_d = event.args) === null || _d === void 0 ? void 0 : _d._metaEvidenceID.toString(),
evidenceGroupId: (_e = event.args) === null || _e === void 0 ? void 0 : _e._evidenceGroupID.toString(),
});
}
catch (error) {
console.warn(`Error processing Dispute event at block ${event.blockNumber}:`, error);
// Add the event with minimal information
results.push({
transactionId: (_f = event.args) === null || _f === void 0 ? void 0 : _f._metaEvidenceID.toString(),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: 0, // Unknown timestamp
disputeId: (_g = event.args) === null || _g === void 0 ? void 0 : _g._disputeID.toNumber(),
arbitrator: (_h = event.args) === null || _h === void 0 ? void 0 : _h._arbitrator,
metaEvidenceId: (_j = event.args) === null || _j === void 0 ? void 0 : _j._metaEvidenceID.toString(),
evidenceGroupId: (_k = event.args) === null || _k === void 0 ? void 0 : _k._evidenceGroupID.toString(),
});
}
}
return results;
}
catch (error) {
console.error("Error in getDisputeEvents:", error);
return []; // Return empty array instead of throwing
}
}
/**
* Gets evidence submission events
* @param transactionId The ID of the transaction
* @param options Optional filter options including fromBlock and toBlock
* @returns An array of evidence submission events
*/
async getEvidenceEvents(transactionId, options) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
try {
const fromBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.fromBlock);
const toBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.toBlock);
console.log(`Getting Evidence events with fromBlock=${fromBlock}, toBlock=${toBlock}`);
// Always use an unfiltered query and filter manually afterward
console.log(`Using unfiltered Evidence query for ID: ${transactionId || "all"}`);
const filter = this.escrowContract.filters.Evidence();
const events = await this.escrowContract.queryFilter(filter, fromBlock, toBlock);
// If transactionId is provided, filter events by evidenceGroupID
const relevantEvents = transactionId
? events.filter((event) => {
var _a;
try {
const eventGroupId = (_a = event.args) === null || _a === void 0 ? void 0 : _a._evidenceGroupID.toString();
return eventGroupId === transactionId;
}
catch (error) {
console.warn(`Error comparing event group ID:`, error);
return false;
}
})
: events;
console.log(`Found ${relevantEvents.length} Evidence events for transaction ${transactionId || "all"}`);
const results = [];
for (const event of relevantEvents) {
try {
const block = await event.getBlock();
results.push({
transactionId: (_a = event.args) === null || _a === void 0 ? void 0 : _a._evidenceGroupID.toString(),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: block.timestamp,
party: (_b = event.args) === null || _b === void 0 ? void 0 : _b._party,
evidence: (_c = event.args) === null || _c === void 0 ? void 0 : _c._evidence,
arbitrator: (_d = event.args) === null || _d === void 0 ? void 0 : _d._arbitrator,
evidenceGroupId: (_e = event.args) === null || _e === void 0 ? void 0 : _e._evidenceGroupID.toString(),
});
}
catch (error) {
console.warn(`Error processing Evidence event at block ${event.blockNumber}:`, error);
// Add the event with minimal information
results.push({
transactionId: (_f = event.args) === null || _f === void 0 ? void 0 : _f._evidenceGroupID.toString(),
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: 0, // Unknown timestamp
party: (_g = event.args) === null || _g === void 0 ? void 0 : _g._party,
evidence: (_h = event.args) === null || _h === void 0 ? void 0 : _h._evidence,
arbitrator: (_j = event.args) === null || _j === void 0 ? void 0 : _j._arbitrator,
evidenceGroupId: (_k = event.args) === null || _k === void 0 ? void 0 : _k._evidenceGroupID.toString(),
});
}
}
return results;
}
catch (error) {
console.error("Error in getEvidenceEvents:", error);
return []; // Return empty array instead of throwing
}
}
/**
* Gets ruling events
* @param transactionId The ID of the transaction
* @param options Optional filter options including fromBlock and toBlock
* @returns An array of ruling events
*/
async getRulingEvents(transactionId, options) {
var _a, _b, _c, _d, _e, _f, _g;
try {
const fromBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.fromBlock);
const toBlock = this.normalizeBlockParam(options === null || options === void 0 ? void 0 : options.toBlock);
console.log(`Getting Ruling events with fromBlock=${fromBlock}, toBlock=${toBlock}`);
let disputeId;
// If transactionId is provided, get the disputeId
if (transactionId) {
try {
const tx = await this.escrowContract.transactions(transactionId);
disputeId = tx.disputeId.toNumber();
if (disputeId === 0) {
return [];
}
}
catch (error) {
console.warn(`Error getting transaction ${transactionId} for dispute ID:`, error);
return [];
}
}
const filter = this.escrowContract.filters.Ruling(null, disputeId);
const events = await this.escrowContract.queryFilter(filter, fromBlock, toBlock);
const results = [];
for (const event of events) {
try {
const block = await event.getBlock();
// If we don't have a transactionId, we need to find it
let txId = transactionId;
if (!txId) {
try {
// This is a simplified approach - in a real implementation, you might want to use a more efficient method
// Limit the search to a reasonable number to prevent timeouts
const MAX_TX_TO_CHECK = 100;
const count = await this.escrowContract.getCountTransactions();
const txCount = Math.min(count.toNumber(), MAX_TX_TO_CHECK);
for (let i = 0; i < txCount; i++) {
const tx = await this.escrowContract.transactions(i);
if (tx.disputeId.eq((_a = event.args) === null || _a === void 0 ? void 0 : _a._disputeID)) {
txId = i.toString();
break;
}
}
}
catch (error) {
console.error("Error finding transaction ID for dispute:", error);
txId = "unknown";
}
}
results.push({
transactionId: txId || "unknown",
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: block.timestamp,
disputeId: (_b = event.args) === null || _b === void 0 ? void 0 : _b._disputeID.toNumber(),
ruling: (_c = event.args) === null || _c === void 0 ? void 0 : _c._ruling.toNumber(),
arbitrator: (_d = event.args) === null || _d === void 0 ? void 0 : _d._arbitrator,
});
}
catch (error) {
console.warn(`Error processing Ruling event at block ${event.blockNumber}:`, error);
// Add the event with minimal information
results.push({
transactionId: transactionId || "unknown",
blockNumber: event.blockNumber,
transactionHash: event.transactionHash,
timestamp: 0, // Unknown timestamp
disputeId: (_e = event.args) === null || _e === void 0 ? void 0 : _e._disputeID.toNumber(),
ruling: (_f = event.args) === null || _f === void 0 ? void 0 : _f._ruling.toNumber(),
arbitrator: (_g = event.args) === null || _g === void 0 ? void 0 : _g._arbitrator,
});
}
}
return results;
}
catch (error) {
console.error("Error in getRulingEvents:", error);
return []; // Return empty array instead of throwing
}
}
}