-
Notifications
You must be signed in to change notification settings - Fork 117
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
[IND-387] add script to parse block and print json #692
Conversation
WalkthroughThe changes introduce a Kafka consumer for processing messages in a blockchain indexer service. The updates include new environment variables, configuration schemas, and helper functions for handling Kafka messages. The code also introduces new types for annotated Tendermint events and blocks, and a function to decode these events based on their subtype. Changes
TipsChat with CodeRabbit Bot (
|
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.
Review Status
Actionable comments generated: 4
Configuration used: CodeRabbit UI
Files ignored due to filter (2)
- indexer/pnpm-lock.yaml
- indexer/services/scripts/package.json
Files selected for processing (5)
- indexer/services/scripts/.env (1 hunks)
- indexer/services/scripts/src/config.ts (1 hunks)
- indexer/services/scripts/src/helpers/block-helpers.ts (1 hunks)
- indexer/services/scripts/src/helpers/types.ts (1 hunks)
- indexer/services/scripts/src/print-block.ts (1 hunks)
Files skipped from review due to trivial changes (2)
- indexer/services/scripts/.env
- indexer/services/scripts/src/config.ts
Additional comments: 1
indexer/services/scripts/src/helpers/types.ts (1)
- 1-9: The new interfaces
AnnotatedIndexerTendermintEvent
andAnnotatedIndexerTendermintBlock
extend the existingIndexerTendermintEvent
andIndexerTendermintBlock
interfaces respectively. TheAnnotatedIndexerTendermintEvent
interface adds adata
property of typestring
to store the decoded event data. TheAnnotatedIndexerTendermintBlock
interface adds anannotatedEvents
property, which is an array ofAnnotatedIndexerTendermintEvent
objects. This seems to be a good approach to add annotated data to the existing event and block structures without modifying them directly. However, ensure that thedata
property inAnnotatedIndexerTendermintEvent
andannotatedEvents
property inAnnotatedIndexerTendermintBlock
are being properly populated in the code where these interfaces are used.
if (!message || !message.value || !message.timestamp) { | ||
throw Error('Empty message'); | ||
} | ||
const messageValueBinary: Uint8Array = new Uint8Array(message.value); | ||
|
||
const block: IndexerTendermintBlock = IndexerTendermintBlock.decode( | ||
messageValueBinary, | ||
); | ||
|
||
return block; | ||
} |
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.
The function getIndexerTendermintBlock
throws an error if the message, its value, or its timestamp is not present. However, it does not handle the case where the IndexerTendermintBlock.decode
function fails to decode the message value. This could lead to unhandled exceptions if the message value is not a valid IndexerTendermintBlock
. Consider adding error handling for this case.
const block: IndexerTendermintBlock = IndexerTendermintBlock.decode(
messageValueBinary,
);
Committable suggestion (Beta)
if (!message || !message.value || !message.timestamp) { | |
throw Error('Empty message'); | |
} | |
const messageValueBinary: Uint8Array = new Uint8Array(message.value); | |
const block: IndexerTendermintBlock = IndexerTendermintBlock.decode( | |
messageValueBinary, | |
); | |
return block; | |
} | |
try { | |
const block: IndexerTendermintBlock = IndexerTendermintBlock.decode( | |
messageValueBinary, | |
); | |
return block; | |
} catch (error) { | |
logger.error({ | |
at: 'getIndexerTendermintBlock', | |
message: 'Failed to decode message value', | |
error, | |
}); | |
return undefined; | |
} |
_.forEach(indexerTendermintBlock.events, (event: IndexerTendermintEvent) => { | ||
const annotatedEvent: | ||
AnnotatedIndexerTendermintEvent | undefined = annotateIndexerTendermintEvent( | ||
event, | ||
); | ||
if (annotatedEvent === undefined) { | ||
logger.error({ | ||
at: 'printMessageAtHeight', | ||
message: 'Failed to parse event', | ||
event, | ||
}); | ||
throw Error('Failed to parse event'); | ||
} | ||
annotatedEvents.push(annotatedEvent); | ||
}); |
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.
The function printMessageAtHeight
throws an error if it fails to annotate an event. However, it does not handle the case where the annotateIndexerTendermintEvent
function returns undefined
. This could lead to unhandled exceptions if the function fails to annotate an event. Consider adding error handling for this case.
if (annotatedEvent === undefined) {
logger.error({
at: 'printMessageAtHeight',
message: 'Failed to parse event',
event,
});
throw Error('Failed to parse event');
}
Committable suggestion (Beta)
_.forEach(indexerTendermintBlock.events, (event: IndexerTendermintEvent) => { | |
const annotatedEvent: | |
AnnotatedIndexerTendermintEvent | undefined = annotateIndexerTendermintEvent( | |
event, | |
); | |
if (annotatedEvent === undefined) { | |
logger.error({ | |
at: 'printMessageAtHeight', | |
message: 'Failed to parse event', | |
event, | |
}); | |
throw Error('Failed to parse event'); | |
} | |
annotatedEvents.push(annotatedEvent); | |
}); | |
if (annotatedEvent === undefined) { | |
logger.error({ | |
at: 'printMessageAtHeight', | |
message: 'Failed to annotate event', | |
event, | |
}); | |
return; | |
} |
export function annotateIndexerTendermintEvent( | ||
event: IndexerTendermintEvent, | ||
): AnnotatedIndexerTendermintEvent | undefined { | ||
const eventDataBinary: Uint8Array = event.dataBytes; | ||
switch (event.subtype) { | ||
case (DydxIndexerSubtypes.ORDER_FILL.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(OrderFillEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.SUBACCOUNT_UPDATE.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(SubaccountUpdateEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.TRANSFER.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(TransferEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.MARKET.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(MarketEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.STATEFUL_ORDER.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(StatefulOrderEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.FUNDING.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(FundingEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.ASSET.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(AssetCreateEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.PERPETUAL_MARKET.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(PerpetualMarketCreateEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.LIQUIDITY_TIER.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(LiquidityTierUpsertEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.UPDATE_PERPETUAL.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(UpdatePerpetualEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
case (DydxIndexerSubtypes.UPDATE_CLOB_PAIR.toString()): { | ||
return { | ||
...event, | ||
dataBytes: new Uint8Array(), | ||
data: JSON.stringify(UpdateClobPairEventV1.decode(eventDataBinary)), | ||
}; | ||
} | ||
default: { | ||
const message: string = `Unable to parse event subtype: ${event.subtype}`; | ||
logger.error({ | ||
at: 'block-helpers#annotateIndexerTendermintEvent', | ||
message, | ||
}); | ||
return undefined; | ||
} | ||
} | ||
} |
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.
The annotateIndexerTendermintEvent
function is decoding the dataBytes
of the event based on its subtype
and converting it to a JSON string. This is a good approach for handling different types of events. However, there is a potential performance issue here. Each time a new event comes in, a new Uint8Array
is created and assigned to dataBytes
, even though the original dataBytes
is not used anymore. This could lead to unnecessary memory allocation and garbage collection. Consider setting dataBytes
to null
instead to free up memory.
- dataBytes: new Uint8Array(),
+ dataBytes: null,
Committable suggestion (Beta)
export function annotateIndexerTendermintEvent( | |
event: IndexerTendermintEvent, | |
): AnnotatedIndexerTendermintEvent | undefined { | |
const eventDataBinary: Uint8Array = event.dataBytes; | |
switch (event.subtype) { | |
case (DydxIndexerSubtypes.ORDER_FILL.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(OrderFillEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.SUBACCOUNT_UPDATE.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(SubaccountUpdateEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.TRANSFER.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(TransferEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.MARKET.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(MarketEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.STATEFUL_ORDER.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(StatefulOrderEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.FUNDING.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(FundingEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.ASSET.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(AssetCreateEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.PERPETUAL_MARKET.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(PerpetualMarketCreateEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.LIQUIDITY_TIER.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(LiquidityTierUpsertEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.UPDATE_PERPETUAL.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(UpdatePerpetualEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.UPDATE_CLOB_PAIR.toString()): { | |
return { | |
...event, | |
dataBytes: new Uint8Array(), | |
data: JSON.stringify(UpdateClobPairEventV1.decode(eventDataBinary)), | |
}; | |
} | |
default: { | |
const message: string = `Unable to parse event subtype: ${event.subtype}`; | |
logger.error({ | |
at: 'block-helpers#annotateIndexerTendermintEvent', | |
message, | |
}); | |
return undefined; | |
} | |
} | |
} | |
export function annotateIndexerTendermintEvent( | |
event: IndexerTendermintEvent, | |
): AnnotatedIndexerTendermintEvent | undefined { | |
const eventDataBinary: Uint8Array = event.dataBytes; | |
switch (event.subtype) { | |
case (DydxIndexerSubtypes.ORDER_FILL.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(OrderFillEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.SUBACCOUNT_UPDATE.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(SubaccountUpdateEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.TRANSFER.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(TransferEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.MARKET.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(MarketEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.STATEFUL_ORDER.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(StatefulOrderEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.FUNDING.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(FundingEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.ASSET.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(AssetCreateEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.PERPETUAL_MARKET.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(PerpetualMarketCreateEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.LIQUIDITY_TIER.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(LiquidityTierUpsertEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.UPDATE_PERPETUAL.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(UpdatePerpetualEventV1.decode(eventDataBinary)), | |
}; | |
} | |
case (DydxIndexerSubtypes.UPDATE_CLOB_PAIR.toString()): { | |
return { | |
...event, | |
dataBytes: null, | |
data: JSON.stringify(UpdateClobPairEventV1.decode(eventDataBinary)), | |
}; | |
} | |
default: { | |
const message: string = `Unable to parse event subtype: ${event.subtype}`; | |
logger.error({ | |
at: 'block-helpers#annotateIndexerTendermintEvent', | |
message, | |
}); | |
return undefined; | |
} | |
} | |
} |
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.
Review Status
Actionable comments generated: 2
Configuration used: CodeRabbit UI
Files ignored due to filter (1)
- indexer/services/scripts/package.json
Files selected for processing (1)
- indexer/services/scripts/src/print-block.ts (1 hunks)
Additional comments: 2
indexer/services/scripts/src/print-block.ts (2)
26-36: The function
getIndexerTendermintBlock
now handles the case where theIndexerTendermintBlock.decode
function fails to decode the message value. This is a good improvement as it prevents unhandled exceptions if the message value is not a validIndexerTendermintBlock
.96-110: The function
printMessageAtHeight
now handles the case where theannotateIndexerTendermintEvent
function returnsundefined
. This is a good improvement as it prevents unhandled exceptions if the function fails to annotate an event.
const indexerTendermintBlock: IndexerTendermintBlock | undefined = getIndexerTendermintBlock( | ||
currentMessage, | ||
); | ||
if (indexerTendermintBlock === undefined) { | ||
return; | ||
} | ||
|
||
const currentBlockHeight: number = parseInt(indexerTendermintBlock.height.toString(), 10); | ||
if (currentBlockHeight < targetHeight) { | ||
const offsetToSeek: number = targetHeight - currentBlockHeight + Number(currentMessage.offset); | ||
await seek(BigInt(offsetToSeek)); | ||
} else if (currentBlockHeight === targetHeight) { | ||
const annotatedEvents: AnnotatedIndexerTendermintEvent[] = []; | ||
_.forEach(indexerTendermintBlock.events, (event: IndexerTendermintEvent) => { | ||
const annotatedEvent: | ||
AnnotatedIndexerTendermintEvent | undefined = annotateIndexerTendermintEvent( | ||
event, | ||
); | ||
if (annotatedEvent === undefined) { | ||
logger.error({ | ||
at: 'printMessageAtHeight', | ||
message: 'Failed to parse event', | ||
event, | ||
}); | ||
throw Error('Failed to parse event'); | ||
} | ||
annotatedEvents.push(annotatedEvent); | ||
}); | ||
const annotatedBlock: AnnotatedIndexerTendermintBlock = { | ||
...indexerTendermintBlock, | ||
events: [], | ||
annotatedEvents, | ||
}; | ||
logger.info({ | ||
at: 'printMessageAtHeight', | ||
message: 'Printing block', | ||
block: annotatedBlock, | ||
}); | ||
await stopConsumer(); | ||
} |
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.
The function printMessageAtHeight
still does not handle the case where the current block height is greater than the target height. This could lead to unexpected behavior if the target height is less than the current block height. Consider adding a condition to handle this case.
if (currentBlockHeight < targetHeight) {
const offsetToSeek: number = targetHeight - currentBlockHeight + Number(currentMessage.offset);
await seek(BigInt(offsetToSeek));
} else if (currentBlockHeight === targetHeight) {
Committable suggestion (Beta)
const indexerTendermintBlock: IndexerTendermintBlock | undefined = getIndexerTendermintBlock( | |
currentMessage, | |
); | |
if (indexerTendermintBlock === undefined) { | |
return; | |
} | |
const currentBlockHeight: number = parseInt(indexerTendermintBlock.height.toString(), 10); | |
if (currentBlockHeight < targetHeight) { | |
const offsetToSeek: number = targetHeight - currentBlockHeight + Number(currentMessage.offset); | |
await seek(BigInt(offsetToSeek)); | |
} else if (currentBlockHeight === targetHeight) { | |
const annotatedEvents: AnnotatedIndexerTendermintEvent[] = []; | |
_.forEach(indexerTendermintBlock.events, (event: IndexerTendermintEvent) => { | |
const annotatedEvent: | |
AnnotatedIndexerTendermintEvent | undefined = annotateIndexerTendermintEvent( | |
event, | |
); | |
if (annotatedEvent === undefined) { | |
logger.error({ | |
at: 'printMessageAtHeight', | |
message: 'Failed to parse event', | |
event, | |
}); | |
throw Error('Failed to parse event'); | |
} | |
annotatedEvents.push(annotatedEvent); | |
}); | |
const annotatedBlock: AnnotatedIndexerTendermintBlock = { | |
...indexerTendermintBlock, | |
events: [], | |
annotatedEvents, | |
}; | |
logger.info({ | |
at: 'printMessageAtHeight', | |
message: 'Printing block', | |
block: annotatedBlock, | |
}); | |
await stopConsumer(); | |
} | |
if (currentBlockHeight < targetHeight) { | |
const offsetToSeek: number = targetHeight - currentBlockHeight + Number(currentMessage.offset); | |
await seek(BigInt(offsetToSeek)); | |
} else if (currentBlockHeight > targetHeight) { | |
logger.info({ | |
at: 'printMessageAtHeight', | |
message: 'Current block height is greater than target height', | |
currentBlockHeight, | |
targetHeight, | |
}); | |
await stopConsumer(); | |
} else if (currentBlockHeight === targetHeight) { |
async function start(height: number): Promise<void> { | ||
logger.info({ | ||
at: 'index#start', | ||
message: `Connecting to kafka brokers: ${config.KAFKA_BROKER_URLS}`, | ||
}); | ||
await startKafka(height); | ||
logger.info({ | ||
at: 'index#start', | ||
message: `Successfully connected to kafka brokers: ${config.KAFKA_BROKER_URLS}`, | ||
}); | ||
} |
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.
The start
function logs the Kafka broker URLs before and after starting Kafka. This could potentially expose sensitive information in the logs. Consider removing or obfuscating these logs.
logger.info({
at: 'index#start',
message: `Connecting to kafka brokers: ${config.KAFKA_BROKER_URLS}`,
});
await startKafka(height);
logger.info({
at: 'index#start',
message: `Successfully connected to kafka brokers: ${config.KAFKA_BROKER_URLS}`,
});
Committable suggestion (Beta)
async function start(height: number): Promise<void> { | |
logger.info({ | |
at: 'index#start', | |
message: `Connecting to kafka brokers: ${config.KAFKA_BROKER_URLS}`, | |
}); | |
await startKafka(height); | |
logger.info({ | |
at: 'index#start', | |
message: `Successfully connected to kafka brokers: ${config.KAFKA_BROKER_URLS}`, | |
}); | |
} | |
logger.info({ | |
at: 'index#start', | |
message: `Connecting to kafka brokers`, | |
}); | |
await startKafka(height); | |
logger.info({ | |
at: 'index#start', | |
message: `Successfully connected to kafka brokers`, | |
}); |
|
||
import { AnnotatedIndexerTendermintEvent } from './types'; | ||
|
||
export enum DydxIndexerSubtypes { |
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.
nit: move to types
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.
done
}); | ||
} | ||
|
||
const args = yargs.options({ |
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.
nit: only if it's easy to do, can we also add support to just parse a block at a particular offset
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 don't think this is needed, since all Ender logs printing out offset should also print out block height
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.
Review Status
Actionable comments generated: 0
Configuration used: CodeRabbit UI
Files selected for processing (2)
- indexer/services/scripts/src/helpers/block-helpers.ts (1} hunks)
- indexer/services/scripts/src/helpers/types.ts (1} hunks)
Files skipped from review due to trivial changes (1)
- indexer/services/scripts/src/helpers/block-helpers.ts
Additional comments: 1
indexer/services/scripts/src/helpers/types.ts (1)
- 1-23: The new interfaces
AnnotatedIndexerTendermintEvent
andAnnotatedIndexerTendermintBlock
extend the existingIndexerTendermintEvent
andIndexerTendermintBlock
interfaces respectively. TheAnnotatedIndexerTendermintEvent
interface includes a newdata
property of type string. TheAnnotatedIndexerTendermintBlock
interface includes a newannotatedEvents
property which is an array ofAnnotatedIndexerTendermintEvent
.The
DydxIndexerSubtypes
enum is introduced to represent the different subtypes of events that can occur in the system.These changes seem to be in line with the PR summary and there doesn't appear to be any issues with them. However, ensure that these new interfaces and enum are used correctly in the rest of the codebase.
Changelist
add script to parse block and return json
Test Plan
ran on devbox
Author/Reviewer Checklist
state-breaking
label.PrepareProposal
orProcessProposal
, manually add the labelproposal-breaking
.feature:[feature-name]
.backport/[branch-name]
.refactor
,chore
,bug
.