-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: implement get events #50
Changes from 3 commits
09ec614
3858030
d845dd9
5f946da
9effca9
fd5a1f1
5344f9c
e0d11c0
ecf15f5
cad9ae6
10aba16
4e39307
eb2d090
77ada49
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export class InvalidBlockRangeError extends Error { | ||
constructor(fromBlock: bigint, toBlock: bigint) { | ||
super( | ||
`Invalid block range: fromBlock (${fromBlock}) must be less than or equal to toBlock (${toBlock})`, | ||
); | ||
this.name = "InvalidBlockRangeError"; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,4 +1,4 @@ | ||||||||||||||
import { Caip2ChainId, Caip2Utils, InvalidChainId } from "@ebo-agent/blocknumber"; | ||||||||||||||
import { Caip2ChainId, Caip2Utils, InvalidChainId } from "@ebo-agent/blocknumber/src/index.js"; | ||||||||||||||
import { | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here |
||||||||||||||
AbiEvent, | ||||||||||||||
Address, | ||||||||||||||
|
@@ -41,6 +41,7 @@ import { | |||||||||||||
import { | ||||||||||||||
DecodeLogDataFailure, | ||||||||||||||
InvalidAccountOnClient, | ||||||||||||||
InvalidBlockRangeError, | ||||||||||||||
RpcUrlsEmpty, | ||||||||||||||
TransactionExecutionError, | ||||||||||||||
UnsupportedEvent, | ||||||||||||||
|
@@ -284,7 +285,7 @@ export class ProtocolProvider implements IProtocolProvider { | |||||||||||||
data: log.data, | ||||||||||||||
topics: log.topics, | ||||||||||||||
eventName, | ||||||||||||||
strict: false, | ||||||||||||||
strict: true, | ||||||||||||||
}); | ||||||||||||||
|
||||||||||||||
return decodedLog.args as DecodedLogArgsMap[TEventName]; | ||||||||||||||
|
@@ -301,87 +302,39 @@ export class ProtocolProvider implements IProtocolProvider { | |||||||||||||
* @returns An EboEvent object. | ||||||||||||||
*/ | ||||||||||||||
private parseOracleEvent(eventName: EboEventName, log: Log) { | ||||||||||||||
if ( | ||||||||||||||
![ | ||||||||||||||
"ResponseProposed", | ||||||||||||||
"ResponseDisputed", | ||||||||||||||
"DisputeStatusChanged", | ||||||||||||||
"DisputeEscalated", | ||||||||||||||
"RequestFinalized", | ||||||||||||||
].includes(eventName) | ||||||||||||||
) { | ||||||||||||||
throw new UnsupportedEvent(`Unsupported event name: ${eventName}`); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
const baseEvent = { | ||||||||||||||
name: eventName, | ||||||||||||||
blockNumber: log.blockNumber ?? BigInt(0), | ||||||||||||||
logIndex: log.logIndex ?? 0, | ||||||||||||||
blockNumber: log.blockNumber, | ||||||||||||||
logIndex: log.logIndex, | ||||||||||||||
rawLog: log, | ||||||||||||||
requestId: log.topics[1] as RequestId, | ||||||||||||||
}; | ||||||||||||||
|
||||||||||||||
const decodedLog = this.decodeLogData(eventName, log); | ||||||||||||||
|
||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. After setting
Suggested change
I feel like there has to be a way to generalize this somehow, I might be wrong though. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I haven't found a way to get this to work yet, not sure if the ABI types are coming through properly There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could it be that the event's properties are prefixed with an underscore and we need to replicate those in our codebase? Let's grab this event for example:
The corresponding type inside
Maybe refactoring those attributes by prefixing them with an underscore would comply with the ABI types? Feel free to do some quick validation on this. |
||||||||||||||
let requestId: RequestId; | ||||||||||||||
switch (eventName) { | ||||||||||||||
case "ResponseProposed": | ||||||||||||||
const responseProposedArgs = decodedLog as DecodedLogArgsMap["ResponseProposed"]; | ||||||||||||||
return { | ||||||||||||||
...baseEvent, | ||||||||||||||
metadata: { | ||||||||||||||
requestId: responseProposedArgs.requestId, | ||||||||||||||
responseId: responseProposedArgs.responseId, | ||||||||||||||
response: responseProposedArgs.response, | ||||||||||||||
blockNumber: responseProposedArgs.blockNumber, | ||||||||||||||
}, | ||||||||||||||
}; | ||||||||||||||
requestId = decodedLog.requestId; | ||||||||||||||
break; | ||||||||||||||
case "ResponseDisputed": | ||||||||||||||
const responseDisputedArgs = decodedLog as DecodedLogArgsMap["ResponseDisputed"]; | ||||||||||||||
return { | ||||||||||||||
...baseEvent, | ||||||||||||||
metadata: { | ||||||||||||||
responseId: responseDisputedArgs.responseId, | ||||||||||||||
disputeId: responseDisputedArgs.disputeId, | ||||||||||||||
dispute: responseDisputedArgs.dispute, | ||||||||||||||
blockNumber: responseDisputedArgs.blockNumber, | ||||||||||||||
}, | ||||||||||||||
}; | ||||||||||||||
requestId = decodedLog.requestId; | ||||||||||||||
break; | ||||||||||||||
case "DisputeStatusChanged": | ||||||||||||||
const disputeStatusChangedArgs = | ||||||||||||||
decodedLog as DecodedLogArgsMap["DisputeStatusChanged"]; | ||||||||||||||
return { | ||||||||||||||
...baseEvent, | ||||||||||||||
metadata: { | ||||||||||||||
disputeId: disputeStatusChangedArgs.disputeId, | ||||||||||||||
dispute: disputeStatusChangedArgs.dispute, | ||||||||||||||
status: disputeStatusChangedArgs.status, | ||||||||||||||
blockNumber: disputeStatusChangedArgs.blockNumber, | ||||||||||||||
}, | ||||||||||||||
}; | ||||||||||||||
case "DisputeEscalated": | ||||||||||||||
const disputeEscalatedArgs = decodedLog as DecodedLogArgsMap["DisputeEscalated"]; | ||||||||||||||
return { | ||||||||||||||
...baseEvent, | ||||||||||||||
metadata: { | ||||||||||||||
caller: disputeEscalatedArgs.caller, | ||||||||||||||
disputeId: disputeEscalatedArgs.disputeId, | ||||||||||||||
blockNumber: disputeEscalatedArgs.blockNumber, | ||||||||||||||
}, | ||||||||||||||
}; | ||||||||||||||
requestId = decodedLog.requestId; | ||||||||||||||
break; | ||||||||||||||
case "RequestFinalized": | ||||||||||||||
const requestFinalizedArgs = decodedLog as DecodedLogArgsMap["RequestFinalized"]; | ||||||||||||||
return { | ||||||||||||||
...baseEvent, | ||||||||||||||
metadata: { | ||||||||||||||
requestId: requestFinalizedArgs.requestId, | ||||||||||||||
responseId: requestFinalizedArgs.responseId, | ||||||||||||||
caller: requestFinalizedArgs.caller, | ||||||||||||||
blockNumber: requestFinalizedArgs.blockNumber, | ||||||||||||||
}, | ||||||||||||||
}; | ||||||||||||||
requestId = decodedLog.requestId; | ||||||||||||||
break; | ||||||||||||||
default: | ||||||||||||||
throw new UnsupportedEvent(`Unsupported event name: ${eventName}`); | ||||||||||||||
throw new Error(`Unsupported event name: ${eventName}`); | ||||||||||||||
} | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was removing There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I think this happened when i was merging things. Added it back in |
||||||||||||||
|
||||||||||||||
return { | ||||||||||||||
...baseEvent, | ||||||||||||||
requestId, | ||||||||||||||
metadata: decodedLog, | ||||||||||||||
}; | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
/** | ||||||||||||||
|
@@ -399,31 +352,30 @@ export class ProtocolProvider implements IProtocolProvider { | |||||||||||||
"DisputeEscalated", | ||||||||||||||
"RequestFinalized", | ||||||||||||||
]; | ||||||||||||||
const eventPromises = eventNames.map((eventName) => | ||||||||||||||
this.readClient.getLogs({ | ||||||||||||||
address: this.oracleContract.address, | ||||||||||||||
event: oracleAbi.find( | ||||||||||||||
(e) => e.name === eventName && e.type === "event", | ||||||||||||||
) as AbiEvent, | ||||||||||||||
fromBlock, | ||||||||||||||
toBlock, | ||||||||||||||
}), | ||||||||||||||
); | ||||||||||||||
|
||||||||||||||
const allLogs = await Promise.all(eventPromises); | ||||||||||||||
return allLogs.flatMap((logs: Log[], index: number) => | ||||||||||||||
logs.map((log) => this.parseOracleEvent(eventNames[index] as EboEventName, log)), | ||||||||||||||
); | ||||||||||||||
} | ||||||||||||||
const logs = await this.readClient.getLogs({ | ||||||||||||||
address: this.oracleContract.address, | ||||||||||||||
events: eventNames.map( | ||||||||||||||
(eventName) => | ||||||||||||||
oracleAbi.find((e) => e.name === eventName && e.type === "event") as AbiEvent, | ||||||||||||||
), | ||||||||||||||
fromBlock, | ||||||||||||||
toBlock, | ||||||||||||||
strict: true, | ||||||||||||||
}); | ||||||||||||||
|
||||||||||||||
return logs.map((log) => { | ||||||||||||||
const eventName = log.eventName as EboEventName; | ||||||||||||||
return this.parseOracleEvent(eventName, log); | ||||||||||||||
}); | ||||||||||||||
} | ||||||||||||||
/** | ||||||||||||||
* Fetches events from the EBORequestCreator contract. | ||||||||||||||
* | ||||||||||||||
* @param fromBlock - The starting block number to fetch events from. | ||||||||||||||
* @param toBlock - The ending block number to fetch events to. | ||||||||||||||
* @returns A promise that resolves to an array of EboEvents. | ||||||||||||||
*/ | ||||||||||||||
|
||||||||||||||
private async getEBORequestCreatorEvents(fromBlock: bigint, toBlock: bigint) { | ||||||||||||||
const logs = await this.readClient.getLogs({ | ||||||||||||||
address: this.eboRequestCreatorContract.address, | ||||||||||||||
|
@@ -441,15 +393,11 @@ export class ProtocolProvider implements IProtocolProvider { | |||||||||||||
) as DecodedLogArgsMap["RequestCreated"]; | ||||||||||||||
return { | ||||||||||||||
name: "RequestCreated" as const, | ||||||||||||||
blockNumber: log.blockNumber ?? BigInt(0), | ||||||||||||||
logIndex: log.logIndex ?? 0, | ||||||||||||||
blockNumber: log.blockNumber, | ||||||||||||||
logIndex: log.logIndex, | ||||||||||||||
rawLog: log, | ||||||||||||||
requestId: decodedLog.requestId, | ||||||||||||||
metadata: { | ||||||||||||||
epoch: decodedLog.epoch, | ||||||||||||||
chainId: decodedLog.chainId, | ||||||||||||||
requestId: decodedLog.requestId, | ||||||||||||||
}, | ||||||||||||||
requestId: decodedLog.requestId ?? "", | ||||||||||||||
metadata: decodedLog, | ||||||||||||||
}; | ||||||||||||||
}); | ||||||||||||||
} | ||||||||||||||
|
@@ -464,7 +412,7 @@ export class ProtocolProvider implements IProtocolProvider { | |||||||||||||
*/ | ||||||||||||||
async getEvents(fromBlock: bigint, toBlock: bigint) { | ||||||||||||||
if (fromBlock > toBlock) { | ||||||||||||||
throw new Error("Invalid block range: fromBlock must be less than or equal to toBlock"); | ||||||||||||||
throw new InvalidBlockRangeError(fromBlock, toBlock); | ||||||||||||||
} | ||||||||||||||
|
||||||||||||||
const [requestCreatorEvents, oracleEvents] = await Promise.all([ | ||||||||||||||
|
@@ -487,11 +435,11 @@ export class ProtocolProvider implements IProtocolProvider { | |||||||||||||
return streams | ||||||||||||||
.reduce((acc, curr) => acc.concat(curr), []) | ||||||||||||||
.sort((a, b) => { | ||||||||||||||
if (a.blockNumber < b.blockNumber) return 1; | ||||||||||||||
if (a.blockNumber > b.blockNumber) return -1; | ||||||||||||||
if (a.blockNumber > b.blockNumber) return 1; | ||||||||||||||
if (a.blockNumber < b.blockNumber) return -1; | ||||||||||||||
|
||||||||||||||
if (a.logIndex < b.logIndex) return 1; | ||||||||||||||
if (a.logIndex > b.logIndex) return -1; | ||||||||||||||
if (a.logIndex > b.logIndex) return 1; | ||||||||||||||
if (a.logIndex < b.logIndex) return -1; | ||||||||||||||
|
||||||||||||||
return 0; | ||||||||||||||
}); | ||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
import { BlockNumberService, Caip2ChainId } from "@ebo-agent/blocknumber"; | ||
import { BlockNumberService } from "@ebo-agent/blocknumber"; | ||
import { Caip2ChainId } from "@ebo-agent/blocknumber/src/index.js"; | ||
import { Address, ILogger } from "@ebo-agent/shared"; | ||
import { Mutex } from "async-mutex"; | ||
import { Heap } from "heap-js"; | ||
|
@@ -610,6 +611,7 @@ export class EboActor { | |
const disputer = this.protocolProvider.getAccountAddress(); | ||
const dispute: Dispute["prophetData"] = { | ||
disputer: disputer, | ||
// TODO: populate proposer if does not exist on eventResponse | ||
proposer: eventResponse.proposer, | ||
responseId: Address.normalize(event.metadata.responseId) as ResponseId, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we are ok on this case, as the
And the
Thus, the proposer can be accessed through Do you know any other case that might be broken? [1] https://github.com/defi-wonderland/prophet-core/blob/4d28a0ec7e8cb082f4932c52a0845b122a0ca71a/solidity/interfaces/IOracle.sol#L27 |
||
requestId: request.id, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,7 @@ | ||
import { Caip2ChainId } from "@ebo-agent/blocknumber"; | ||
import { Address, Hex, Log } from "viem"; | ||
import { Caip2ChainId } from "@ebo-agent/blocknumber/src/index.js"; | ||
import { Address, Log } from "viem"; | ||
|
||
import { | ||
Dispute, | ||
DisputeId, | ||
DisputeStatus, | ||
Request, | ||
RequestId, | ||
Response, | ||
ResponseId, | ||
} from "./prophet.js"; | ||
import { DisputeId, DisputeStatus, RequestId, ResponseId } from "./prophet.js"; | ||
|
||
export type EboEventName = | ||
| "RequestCreated" | ||
|
@@ -19,34 +11,31 @@ export type EboEventName = | |
| "DisputeEscalated" | ||
| "RequestFinalized"; | ||
|
||
export interface ResponseProposed { | ||
requestId: Hex; | ||
responseId: Hex; | ||
response: Response["prophetData"]; | ||
// TODO: block number? | ||
} | ||
|
||
export interface RequestCreated { | ||
requestId: RequestId; | ||
epoch: bigint; | ||
chainId: Caip2ChainId; | ||
//TODO: remove request? | ||
request: Request["prophetData"]; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might end up using Oracle's There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So, we'll be using both events, but only reacting to This will probably cause some type failure during request creation internally in the We got GRT-205 already created to tackle this in another PR. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. are the ABIs up to date now since your PR was merged? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oracle's ABI should be up to date, yep. Viem types should be working as expected for all related functionality. |
||
|
||
export interface ResponseProposed { | ||
requestId: RequestId; | ||
responseId: ResponseId; | ||
response: string; | ||
blockNumber: bigint; | ||
} | ||
|
||
export interface ResponseDisputed { | ||
responseId: ResponseId; | ||
disputeId: DisputeId; | ||
dispute: Dispute["prophetData"]; | ||
//TODO: block number? | ||
dispute: string; | ||
blockNumber: bigint; | ||
} | ||
|
||
export interface DisputeStatusChanged { | ||
disputeId: DisputeId; | ||
dispute: Dispute["prophetData"]; | ||
dispute: string; | ||
status: DisputeStatus; | ||
blockNumber: bigint; | ||
//TODO: should be disputeId, request, response,dispute? | ||
} | ||
|
||
export interface DisputeEscalated { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the
blocknumber
package exposesCaip2ChainId
already, it shouldn't be necessary to use/src/index.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the /src/index.js that I added everywhere--not sure why my IDE was flagging it