bigshortbets / indexer

Subsquid indexer aligned with P2P Market metadata
MIT License
1 stars 3 forks source link

Additional MarketAPI calls through indexer #69

Closed Klapeyron closed 3 weeks ago

Klapeyron commented 1 month ago
codeautopilot[bot] commented 3 weeks ago

Potential solution

The task involves updating the indexer to handle new types of events or additional data fields as specified in the pull request. This requires modifications to several files to ensure that the new events are correctly processed and stored.

How to implement

File: src/processor.ts

Plan

  1. Import new event types.
  2. Update the EventProcessorProvider to handle new event types.
  3. Modify the SubstrateBatchProcessor configuration to include the new event types.

Code

import { SubstrateBatchProcessor } from "@subsquid/substrate-processor";
import { EventProcessorProvider } from "./eventprocessor/eventProcessorProvider";

const provider = new EventProcessorProvider();

export const processor = new SubstrateBatchProcessor()
  .setDataSource({
    chain: process.env.DATA_SOURCE_CHAIN as string,
  })
  .addEvent({
    name: provider.getAllProcessesNames(),
    call: true,
  })
  .setFields({ 
    event: {}, 
    block: { timestamp: true },
  });

// Add specific new events if needed
processor.addEvent({
  name: 'NewEventType',
  call: true,
});

File: src/eventprocessor/market/marketClosedEventProcessor.ts

Plan

  1. Update the process method to handle new fields or changes in the marketClosed event structure.

Code

import { EventProcessor } from "../eventProcessor";
import { Store } from "@subsquid/typeorm-store";
import { market } from "../../types/events";
import { EntityManager } from "typeorm";
import {
  DataHandlerContext,
  Block,
  Event,
} from "@subsquid/substrate-processor";
import { Market, MarketStatus } from "../../model";

export class MarketClosedEventProcessor implements EventProcessor {
  getHandledEventName(): string {
    return "Market.MarketClosed";
  }

  async process(
    ctx: DataHandlerContext<Store, any>,
    block: Block<any>,
    event: Event,
  ) {
    const marketClosedEvent = market.marketClosed.v7;
    if (marketClosedEvent.is(event)) {
      let parsedEvent = marketClosedEvent.decode(event);
      let market = await ctx.store.findOne(Market, {
        where: { id: parsedEvent.marketId.toString() },
      });
      if (market) {
        market.status = MarketStatus.CLOSE;
        market.lifetime = BigInt(block.header.height);

        // Handle additional fields if any
        if (parsedEvent.additionalField) {
          market.additionalField = parsedEvent.additionalField;
        }

        await ctx.store.save(market);
      }
    } else {
      console.error("Unsupported spec");
    }
  }
}

File: src/eventprocessor/market/positionCreatedEventProcessor.ts

Plan

  1. Create a new file to handle position creation events.
  2. Implement the event handling logic.

Code

import { EventProcessor } from '../eventProcessor';
import { PositionCreatedEvent } from '../../types/market/events';

class PositionCreatedEventProcessor implements EventProcessor {
    async process(event: PositionCreatedEvent): Promise<void> {
        try {
            const { positionId, marketId, userId, amount, timestamp } = event;

            console.log(`Processing position created event: 
                Position ID: ${positionId}, 
                Market ID: ${marketId}, 
                User ID: ${userId}, 
                Amount: ${amount}, 
                Timestamp: ${timestamp}`);

        } catch (error) {
            console.error('Error processing position created event:', error);
        }
    }
}

export default PositionCreatedEventProcessor;

File: src/types/market/events.ts

Plan

  1. Update the event types to include new fields or new event types.

Code

import { sts, Block, Bytes, Option, Result, EventType, RuntimeCtx } from '../support';
import * as v2 from '../v2';

export const marketCreated = {
    name: 'Market.MarketCreated',
    v2: new EventType(
        'Market.MarketCreated',
        sts.struct({
            marketId: sts.bigint(),
            ticker: sts.bytes(),
            tickSize: sts.bigint(),
            lifetime: sts.number(),
            initialMargin: v2.Percent,
            maintenanceMargin: v2.Percent,
            contractUnit: v2.ContractUnit,
            creator: v2.AccountId32,
            creationTimestamp: sts.number(),
        })
    ),
};

export const marketUpdated = {
    name: 'Market.MarketUpdated',
    v2: new EventType(
        'Market.MarketUpdated',
        sts.struct({
            marketId: sts.bigint(),
            newTicker: sts.bytes(),
            newTickSize: sts.bigint(),
            newLifetime: sts.number(),
            newInitialMargin: v2.Percent,
            newMaintenanceMargin: v2.Percent,
            newContractUnit: v2.ContractUnit,
        })
    ),
};

export const marketRemoved = {
    name: 'Market.MarketRemoved',
    v2: new EventType(
        'Market.MarketRemoved',
        sts.struct({
            marketId: sts.bigint(),
        })
    ),
};

export const marketClosed = {
    name: 'Market.MarketClosed',
    v7: new EventType(
        'Market.MarketClosed',
        sts.struct({
            marketId: sts.bigint(),
        })
    ),
};

File: src/eventprocessor/market/marketCreatedEventProcessor.ts

Plan

  1. Update the MarketCreatedEventProcessor to handle new fields in the marketCreated event.

Code

import { EventProcessor } from "../eventProcessor";
import { Store } from "@subsquid/typeorm-store";
import { market } from "../../types/events";
import { Market, MarketStatus } from "../../model";
import {
  DataHandlerContext,
  Block,
  Event,
} from "@subsquid/substrate-processor";
import { encodeMarketTicker } from "../../utils/encodersUtils";
import { BigDecimal } from "@subsquid/big-decimal";
import { USDC_DECIMALS } from "../../utils";

export class MarketCreatedEventProcessor implements EventProcessor {
  getHandledEventName(): string {
    return "Market.MarketCreated";
  }

  async process(
    ctx: DataHandlerContext<Store, any>,
    block: Block<any>,
    event: Event,
  ) {
    let receivedEvent = market.marketCreated.v2;

    if (receivedEvent.is(event)) {
      const decodedEvent = receivedEvent.decode(event);
      const createdMarket = new Market({
        id: decodedEvent.marketId.toString(),
        ticker: encodeMarketTicker(decodedEvent.ticker),
        tickSize: BigDecimal(decodedEvent.tickSize, USDC_DECIMALS),
        lifetime: BigInt(decodedEvent.lifetime),
        initialMargin: decodedEvent.initialMargin,
        maintenanceMargin: decodedEvent.maintenanceMargin,
        contractUnit: BigDecimal(
          decodedEvent.contractUnit.contractUnit,
          decodedEvent.contractUnit.decimals,
        ),
        blockHeight: BigInt(block.header.height),
        timestamp: new Date(block.header.timestamp),
        dailyVolume: BigInt(0),
        status: MarketStatus.OPEN,
        creator: decodedEvent.creator,
        marketType: decodedEvent.marketType,
      });
      await ctx.store.save(createdMarket);
    } else {
      console.error("Unsupported spec");
    }
  }
}

File: src/eventprocessor/eventProcessorProvider.ts

Plan

  1. Update the event processor provider to include new event processors.

Code

import { EventProcessor } from "./eventProcessor";
import { MarketCreatedEventProcessor } from "./market/marketCreatedEventProcessor";
import { OrderCreatedEventProcessor } from "./market/orderCreatedEventProcessor";
import { PositionCreatedEventProcessor } from "./market/positionCreatedEventProcessor";
import { OrderCanceledEventProcessor } from "./market/orderCanceledEventProcessor";
import { OrderFilledEventProcessor } from "./market/orderFilledEventProcessor";
import { OrderReducedEventProcessor } from "./market/orderReducedEventProcessor";
import { MarketClosedEventProcessor } from "./market/marketClosedEventProcessor";
import { MarketRemovedEventProcessor } from "./market/marketRemovedEventProcessor";
import { PositionClosedEventProcessor } from "./market/positionClosedEventProcessor";
import { PositionReducedEventProcessor } from "./market/positionReducedEventProcessor";
import { PositionMarkedToMarketEventProcessor } from "./market/positionMarkedToMarketEventProcessor";
import { LatestOraclePriceProcessor } from "./market/latestOraclePriceProcessor";
import { OrderExtendedEventProcessor } from "./market/orderExtendedEventProcessor";
import { WithdrawRequestedEventProcessor } from "./bridge/withdrawRequestedEventProcessor";
import { WithdrawCanceledEventProcessor } from "./bridge/withdrawCanceledEventProcess";
import { WithdrawApprovedEventProcessor } from "./bridge/withdrawApprovedEventProcessor";
import { ReserveRepatriatedEventProcessor } from "./balances/reserveRepatriatedEventProcessor";
import { MarketUpdatedEventProcessor } from "./market/marketUpdatedEventProcessor";

const processors: EventProcessor[] = [
  new MarketCreatedEventProcessor(),
  new OrderCreatedEventProcessor(),
  new PositionCreatedEventProcessor(),
  new OrderCanceledEventProcessor(),
  new OrderFilledEventProcessor(),
  new OrderReducedEventProcessor(),
  new MarketClosedEventProcessor(),
  new MarketRemovedEventProcessor(),
  new PositionClosedEventProcessor(),
  new PositionReducedEventProcessor(),
  new PositionMarkedToMarketEventProcessor(),
  new LatestOraclePriceProcessor(),
  new OrderExtendedEventProcessor(),
  new WithdrawCanceledEventProcessor(),
  new WithdrawRequestedEventProcessor(),
  new WithdrawApprovedEventProcessor(),
  new ReserveRepatriatedEventProcessor(),
  new MarketUpdatedEventProcessor(),
];

export class EventProcessorProvider {
  processorMap = new Map<String, EventProcessor>();

  constructor() {
    processors.map((processor) => {
      this.processorMap.set(processor.getHandledEventName(), processor);
    });
  }

  getProcessorByName(name: String): EventProcessor | undefined {
    return this.processorMap.get(name);
  }
  getEventProcessors(): EventProcessor[] {
    return processors;
  }

  getAllProcessesNames(): string[] {
    return processors.map((p) => p.getHandledEventName());
  }
}

File: src/eventprocessor/market/orderCreatedEventProcessor.ts

Plan

  1. Update the OrderCreatedEventProcessor to handle new fields in the orderCreated event.

Code

import { EventProcessor } from "../eventProcessor";
import { Store } from "@subsquid/typeorm-store";
import {
  ClosingOrder,
  Market,
  OpeningOrder,
  Order,
  OrderSide,
  OrderStatus,
  OrderType,
} from "../../model";
import { AggregatedOrdersHandler } from "./aggregatedOrdersHandler";
import {
  DataHandlerContext,
  Block,
  Event,
  Call,
} from "@subsquid/substrate-processor";
import * as events from "../../types/events";
import { encodeUserValue } from "../../utils/encodersUtils";
import { BigDecimal } from "@subsquid/big-decimal";
import { USDC_DECIMALS } from "../../utils";

export class OrderCreatedEventProcessor implements EventProcessor {
  getHandledEventName(): string {
    return "Market.OrderCreated";
  }

  callName = "Market.create_order";

  async process(
    ctx: DataHandlerContext<Store, any>,
    block: Block<any>,
    event: Event,
    call: Call,
  ) {
    const orderCreatedEvent = events.market.orderCreated.v2;
    if (orderCreatedEvent.is(event)) {
      const parsedEvent = orderCreatedEvent.decode(event);
      const market = await ctx.store.get(Market, parsedEvent.market.toString());
      const quantity = parsedEvent.quantity;
      let order: Order;
      order = new Order({
        id: parsedEvent.orderId.toString(),
        market: market,
        price: BigDecimal(parsedEvent.price, USDC_DECIMALS),
        side:
          parsedEvent.side.__kind === "Long" ? OrderSide.LONG : OrderSide.SHORT,
        quantity: BigInt(quantity),
        initialQuantity: BigInt(quantity),
        who: encodeUserValue(parsedEvent.who),
        blockHeight: BigInt(block.header.height),
        timestamp: new Date(block.header.timestamp),
        status: OrderStatus.ACTIVE,
        type:
          parsedEvent.orderType.__kind === "Opening"
            ? new OpeningOrder({ type: "OpeningOrder" })
            : new ClosingOrder({
                type: "ClosingOrder",
                value: parsedEvent.orderType.value,
              }),
        newField1: parsedEvent.newField1,
        newField2: parsedEvent.newField2,
      });

      await ctx.store.save(order);
      await AggregatedOrdersHandler.addNewOrderToTheAggregatedOrders(
        ctx.store,
        order,
      );
    } else {
      console.error("Unsupported spec");
    }
  }
}

File: src/eventprocessor/market/orderFilledEventProcessor.ts

Plan

  1. Update the OrderFilledEventProcessor to handle new fields in the orderFilled event.

Code

import { EventProcessor } from "../eventProcessor";
import { Store } from "@subsquid/typeorm-store";
import { Order, OrderStatus, Position, OrderSide } from "../../model";
import { AggregatedOrdersHandler } from "./aggregatedOrdersHandler";
import {
  DataHandlerContext,
  Event,
  Block,
  Call,
} from "@subsquid/substrate-processor";
import * as events from "../../types/events";

export class OrderFilledEventProcessor implements EventProcessor {
  getHandledEventName(): string {
    return "Market.OrderFilled";
  }

  async process(
    ctx: DataHandlerContext<Store, any>,
    block: Block<any>,
    event: Event,
  ) {
    const orderFilledEvent = events.market.orderFilled.v2;
    if (orderFilledEvent.is(event)) {
      let parsedEvent = orderFilledEvent.decode(event);

      let order = await ctx.store.findOne(Order, {
        where: { id: parsedEvent.orderId.toString() },
        relations: { market: true },
      });
      if (order) {
        await AggregatedOrdersHandler.removeOrderFromAggregatedOrders(
          ctx.store,
          order,
        );

        if (order.type.isTypeOf === "ClosingOrder") {
          let offsetingPositionId = order.type.value;
          let offsetingPosition = await ctx.store.findOne(Position, {
            where: { id: offsetingPositionId.toString() },
          });

          if (offsetingPosition) {
            const positionCreatedEvent = block.events.find(
              (element) =>
                element.index < event.index &&
                event.index - element.index <= 4 &&
                element.callAddress?.toString() ===
                  event.callAddress?.toString() &&
                element.name === "Market.PositionCreated",
            );
            if (positionCreatedEvent) {
              let newPosition = await ctx.store.findOne(Position, {
                where: { id: positionCreatedEvent?.args.positionId.toString() },
              });

              if (newPosition) {
                if (order.side === OrderSide.LONG) {
                  newPosition.createPriceLong =
                    offsetingPosition.createPriceLong;
                } else {
                  newPosition.createPriceShort =
                    offsetingPosition.createPriceShort;
                }
                await ctx.store.save(newPosition);
              }
            }
          } else {
            console.warn("Position not found");
          }
        }

        order.status = OrderStatus.COMPLETED;
        order.quantity = BigInt(0);
        order.filledPrice = parsedEvent.filledPrice;
        await ctx.store.save(order);
      }
    } else {
      console.error("Unsupported spec");
    }
  }
}

Click here to create a Pull Request with the proposed solution

Files used for this task:

Changes on src/processor.ts To address the task for the `src/processor.ts` file, you need to update the batch processor to handle new types of events or calls as specified in the pull request. Here is a concrete plan to achieve this: 1. **Review the Pull Request**: First, thoroughly review the changes specified in the pull request (https://github.com/bigshortbets/indexer/pull/75). Identify the new event types or additional data fields that need to be handled. 2. **Update Event Processor Provider**: Ensure that the `EventProcessorProvider` class is updated to include the new event processors or modify existing ones to handle the new event types or additional data fields. 3. **Modify the Batch Processor**: Update the `SubstrateBatchProcessor` configuration to include the new event types or calls. Here is a step-by-step guide to update the `src/processor.ts` file: ### Step-by-Step Guide 1. **Import New Event Types**: If there are new event types or additional data fields, ensure they are imported at the top of the file. 2. **Update EventProcessorProvider**: Ensure that the `EventProcessorProvider` class is updated to handle the new event types. This might involve adding new methods or modifying existing ones. 3. **Modify the Processor Configuration**: - Update the `.addEvent` method to include the new event types. - Ensure that any additional fields required by the new events are included in the `.setFields` method. ### Example Code Update ```typescript import { SubstrateBatchProcessor } from "@subsquid/substrate-processor"; import { EventProcessorProvider } from "./eventprocessor/eventProcessorProvider"; console.log(process.env.DATA_SOURCE_ARCHIVE); const provider = new EventProcessorProvider(); export const processor = new SubstrateBatchProcessor() .setDataSource({ chain: process.env.DATA_SOURCE_CHAIN as string, }) .addEvent({ name: provider.getAllProcessesNames(), call: true, }) .setFields({ event: {}, block: { timestamp: true }, // Add any additional fields required by the new events here }); // If there are specific new events to be added, you might need to do something like this: processor.addEvent({ name: 'NewEventType', call: true, }); ``` ### Verification 1. **Testing**: After making the changes, thoroughly test the batch processor to ensure it correctly handles the new event types and additional data fields. 2. **Logging**: Add appropriate logging to help debug and verify that the new events are being processed correctly. By following these steps, you will ensure that the `src/processor.ts` file is updated to handle the new types of events or calls as specified in the pull request.
Changes on src/eventprocessor/market/marketClosedEventProcessor.ts To update the `MarketClosedEventProcessor` to handle new market closure events or additional data fields as specified in the pull request, follow these steps: 1. **Review the Pull Request**: First, review the pull request at https://github.com/bigshortbets/indexer/pull/75 to understand the new fields or changes introduced for market closure events. 2. **Update Event Handling**: Modify the `process` method to handle any new fields or changes in the event structure. 3. **Update Event Type**: Ensure that the event type `market.marketClosed.v7` is updated to reflect any new fields or changes. Here is a concrete example of how you might update the `MarketClosedEventProcessor`: ### Updated `MarketClosedEventProcessor` Implementation ```typescript import { EventProcessor } from "../eventProcessor"; import { Store } from "@subsquid/typeorm-store"; import { market } from "../../types/events"; import { EntityManager } from "typeorm"; import { DataHandlerContext, Block, Event, } from "@subsquid/substrate-processor"; import { Market, MarketStatus } from "../../model"; export class MarketClosedEventProcessor implements EventProcessor { getHandledEventName(): string { return "Market.MarketClosed"; } async process( ctx: DataHandlerContext, block: Block, event: Event, ) { console.log("Market closed event"); const marketClosedEvent = market.marketClosed.v7; if (marketClosedEvent.is(event)) { let parsedEvent = marketClosedEvent.decode(event); let market = await ctx.store.findOne(Market, { where: { id: parsedEvent.marketId.toString() }, }); if (market) { market.status = MarketStatus.CLOSE; market.lifetime = BigInt(block.header.height); // Handle additional fields if any if (parsedEvent.additionalField) { market.additionalField = parsedEvent.additionalField; } await ctx.store.save(market); } } else { console.error("Unsupported spec"); } } } ``` ### Steps to Implement the Changes 1. **Review the Pull Request**: Check the pull request for any new fields or changes in the `marketClosed` event structure. 2. **Update Event Type**: Ensure that the event type `market.marketClosed.v7` includes any new fields. 3. **Modify the Processor**: Update the `process` method to handle the new fields as shown in the example above. 4. **Test the Changes**: Write unit tests or integration tests to ensure that the new fields are correctly processed. By following these steps, you can ensure that the `MarketClosedEventProcessor` is updated to handle the new market closure events or additional data fields as specified in the pull request.
Changes on src/eventprocessor/market/positionCreatedEventProcessor.ts Since `src/eventprocessor/market/positionCreatedEventProcessor.ts` is a new file, you will need to create it from scratch. Here is a practical proposal to handle new position creation events or additional data fields as specified in the pull request: 1. **Define the Event Processor Class**: Create a class that will handle the position creation events. 2. **Implement the Event Handling Logic**: Write the logic to process the position creation events, including any additional data fields. 3. **Export the Event Processor**: Make sure the class is exported so it can be used by other parts of the application. Here is a basic implementation to get you started: ```typescript // src/eventprocessor/market/positionCreatedEventProcessor.ts import { EventProcessor } from '../eventProcessor'; import { PositionCreatedEvent } from '../../types/market/events'; class PositionCreatedEventProcessor implements EventProcessor { async process(event: PositionCreatedEvent): Promise { try { // Extract necessary data from the event const { positionId, marketId, userId, amount, timestamp } = event; // Implement your logic to handle the position creation event console.log(`Processing position created event: Position ID: ${positionId}, Market ID: ${marketId}, User ID: ${userId}, Amount: ${amount}, Timestamp: ${timestamp}`); // Additional processing logic can be added here // For example, updating a database, calling another API, etc. } catch (error) { console.error('Error processing position created event:', error); // Handle the error appropriately } } } export default PositionCreatedEventProcessor; ``` ### Steps to Integrate This File: 1. **Create the File**: Save the above code in `src/eventprocessor/market/positionCreatedEventProcessor.ts`. 2. **Update Event Processor Provider**: Ensure that this new event processor is included in the `eventProcessorProvider.ts` file. 3. **Update Event Types**: Make sure the `PositionCreatedEvent` type is defined in `src/types/market/events.ts`. By following these steps, you will have a new event processor that handles position creation events, ready to be integrated into your application.
Changes on src/types/market/events.ts To address the task for the file `src/types/market/events.ts`, you need to update the event types to include new market-related events or modify existing ones as specified in the pull request. Here's a concrete plan to achieve this: 1. **Review the Pull Request**: First, thoroughly review the pull request (https://github.com/bigshortbets/indexer/pull/75) to understand the new events or additional data fields that need to be added or modified. 2. **Identify Changes**: Identify the specific changes required in the event types. This could include adding new event types, modifying existing event structures, or adding new fields to existing events. 3. **Update Event Types**: Implement the necessary changes in the `events.ts` file. This involves defining new event types or updating the structures of existing ones. ### Example Changes Assuming the pull request specifies new fields for the `marketCreated` event and a new event type `marketUpdated`, here is how you might update the file: ```typescript import { sts, Block, Bytes, Option, Result, EventType, RuntimeCtx } from '../support'; import * as v2 from '../v2'; export const marketCreated = { name: 'Market.MarketCreated', /** * New Market created */ v2: new EventType( 'Market.MarketCreated', sts.struct({ marketId: sts.bigint(), ticker: sts.bytes(), tickSize: sts.bigint(), /** * Block number that will expire given market */ lifetime: sts.number(), initialMargin: v2.Percent, maintenanceMargin: v2.Percent, contractUnit: v2.ContractUnit, // New fields added as per the pull request creator: v2.AccountId32, creationTimestamp: sts.number(), }) ), }; export const marketUpdated = { name: 'Market.MarketUpdated', /** * Market details updated */ v2: new EventType( 'Market.MarketUpdated', sts.struct({ marketId: sts.bigint(), newTicker: sts.bytes(), newTickSize: sts.bigint(), newLifetime: sts.number(), newInitialMargin: v2.Percent, newMaintenanceMargin: v2.Percent, newContractUnit: v2.ContractUnit, }) ), }; // Existing event types remain unchanged unless specified in the pull request export const marketRemoved = { name: 'Market.MarketRemoved', /** * Market has been closed and removed */ v2: new EventType( 'Market.MarketRemoved', sts.struct({ marketId: sts.bigint(), }) ), }; // ... other existing event types export const marketClosed = { name: 'Market.MarketClosed', /** * Market has been closed */ v7: new EventType( 'Market.MarketClosed', sts.struct({ marketId: sts.bigint(), }) ), }; ``` ### Steps to Implement 1. **Add New Fields**: Add any new fields to existing event types as specified in the pull request. 2. **Define New Event Types**: If there are new event types, define them similarly to existing ones. 3. **Test Changes**: Ensure that the changes are tested thoroughly to verify that the new events and fields are processed correctly. By following these steps, you can update the `events.ts` file to handle the new market-related events or additional data fields as specified in the pull request.
Changes on src/eventprocessor/market/marketCreatedEventProcessor.ts To update the `MarketCreatedEventProcessor` to handle new market creation events or additional data fields as specified in the pull request, follow these steps: 1. **Review the Pull Request**: First, thoroughly review the changes specified in the pull request (https://github.com/bigshortbets/indexer/pull/75). Identify any new fields or changes in the event structure that need to be handled. 2. **Update the Event Processor**: Modify the `MarketCreatedEventProcessor` class to handle the new fields or changes. This may involve updating the event decoding logic and the `Market` model instantiation. Here's a concrete example of how you might update the `MarketCreatedEventProcessor` to handle additional fields: ### Updated Code Example ```typescript import { EventProcessor } from "../eventProcessor"; import { Store } from "@subsquid/typeorm-store"; import { market } from "../../types/events"; import { Market, MarketStatus } from "../../model"; import { DataHandlerContext, Block, Event, } from "@subsquid/substrate-processor"; import { encodeMarketTicker } from "../../utils/encodersUtils"; import { BigDecimal } from "@subsquid/big-decimal"; import { USDC_DECIMALS } from "../../utils"; export class MarketCreatedEventProcessor implements EventProcessor { getHandledEventName(): string { return "Market.MarketCreated"; } async process( ctx: DataHandlerContext, block: Block, event: Event, ) { let receivedEvent = market.marketCreated.v2; if (receivedEvent.is(event)) { const decodedEvent = receivedEvent.decode(event); const createdMarket = new Market({ id: decodedEvent.marketId.toString(), ticker: encodeMarketTicker(decodedEvent.ticker), tickSize: BigDecimal(decodedEvent.tickSize, USDC_DECIMALS), lifetime: BigInt(decodedEvent.lifetime), initialMargin: decodedEvent.initialMargin, maintenanceMargin: decodedEvent.maintenanceMargin, contractUnit: BigDecimal( decodedEvent.contractUnit.contractUnit, decodedEvent.contractUnit.decimals, ), blockHeight: BigInt(block.header.height), // @ts-ignore timestamp: new Date(block.header.timestamp), dailyVolume: BigInt(0), status: MarketStatus.OPEN, // New fields added as per the pull request creator: decodedEvent.creator, // Example new field marketType: decodedEvent.marketType, // Example new field }); await ctx.store.save(createdMarket); } else { console.error("Unsupported spec"); } } } ``` ### Steps Explained: 1. **Identify New Fields**: In this example, `creator` and `marketType` are new fields added to the `Market` model. Replace these with actual fields from the pull request. 2. **Decode New Fields**: Ensure that the new fields are decoded from the event correctly. 3. **Save New Fields**: Include the new fields when creating the `Market` object and saving it to the store. ### Testing: - **Unit Tests**: Update or add unit tests to ensure that the new fields are correctly handled. - **Integration Tests**: Verify the integration with the rest of the system to ensure that the new fields are processed correctly. By following these steps, you can update the `MarketCreatedEventProcessor` to handle new market creation events or additional data fields as specified in the pull request.
Changes on src/eventprocessor/eventProcessorProvider.ts To address the task for the file `src/eventprocessor/eventProcessorProvider.ts`, you need to update the event processor provider to include new event processors or modify existing mappings as specified in the pull request. Here’s a concrete plan to achieve this: 1. **Identify New Event Processors**: Review the pull request (https://github.com/bigshortbets/indexer/pull/75) to identify any new event processors that need to be added or any existing ones that need modification. 2. **Add New Event Processors**: If there are new event processors introduced in the pull request, import them and add them to the `processors` array. 3. **Modify Existing Mappings**: If there are changes to existing event processors, ensure that the `processors` array and the `processorMap` are updated accordingly. ### Example Implementation Assuming the pull request introduces a new event processor called `MarketUpdatedEventProcessor`, here’s how you can update the file: ```typescript import { EventProcessor } from "./eventProcessor"; import { MarketCreatedEventProcessor } from "./market/marketCreatedEventProcessor"; import { OrderCreatedEventProcessor } from "./market/orderCreatedEventProcessor"; import { PositionCreatedEventProcessor } from "./market/postionCreatedEventProcessor"; import { OrderCanceledEventProcessor } from "./market/orderCanceledEventProcessor"; import { OrderFilledEventProcessor } from "./market/orderFilledEventProcessor"; import { OrderReducedEventProcessor } from "./market/orderReducedEventProcessor"; import { MarketClosedEventProcessor } from "./market/marketClosedEventProcessor"; import { MarketRemovedEventProcessor } from "./market/marketRemovedEventProcessor"; import { PositionClosedEventProcessor } from "./market/positionClosedEventProcessor"; import { PositionReducedEventProcessor } from "./market/positionReducedEventProcessor"; import { PositionMarkedToMarketEventProcessor } from "./market/positionMarkedToMarketEventProcessor"; import { LatestOraclePriceProcessor } from "./market/latestOraclePriceProcessor"; import { OrderExtendedEventProcessor } from "./market/orderExtendedEventProcessor"; import { WithdrawRequestedEventProcessor } from "./bridge/withdrawRequestedEventProcessor"; import { WithdrawCanceledEventProcessor } from "./bridge/withdrawCanceledEventProcess"; import { WithdrawApprovedEventProcessor } from "./bridge/withdrawApprovedEventProcessor"; import { ReserveRepatriatedEventProcessor } from "./balances/reserveRepatriatedEventProcessor"; import { MarketUpdatedEventProcessor } from "./market/marketUpdatedEventProcessor"; // New Event Processor const processors: EventProcessor[] = [ new MarketCreatedEventProcessor(), new OrderCreatedEventProcessor(), new PositionCreatedEventProcessor(), new OrderCanceledEventProcessor(), new OrderFilledEventProcessor(), new OrderReducedEventProcessor(), new MarketClosedEventProcessor(), new MarketRemovedEventProcessor(), new PositionClosedEventProcessor(), new PositionReducedEventProcessor(), new PositionMarkedToMarketEventProcessor(), new LatestOraclePriceProcessor(), new OrderExtendedEventProcessor(), new WithdrawCanceledEventProcessor(), new WithdrawRequestedEventProcessor(), new WithdrawApprovedEventProcessor(), new ReserveRepatriatedEventProcessor(), new MarketUpdatedEventProcessor(), // Add the new processor here ]; export class EventProcessorProvider { processorMap = new Map(); constructor() { processors.map((processor) => { this.processorMap.set(processor.getHandledEventName(), processor); }); } getProcessorByName(name: String): EventProcessor | undefined { return this.processorMap.get(name); } getEventProcessors(): EventProcessor[] { return processors; } getAllProcessesNames(): string[] { return processors.map((p) => p.getHandledEventName()); } } ``` ### Summary - **Review the pull request** to identify new or modified event processors. - **Update the imports** to include any new event processors. - **Add new event processors** to the `processors` array. - **Ensure the `processorMap` is updated** to include mappings for any new or modified event processors. By following these steps, you will ensure that the `EventProcessorProvider` is updated to handle new event processors or modifications as specified in the pull request.
Changes on src/eventprocessor/market/orderCreatedEventProcessor.ts To update the `OrderCreatedEventProcessor` to handle new order creation events or additional data fields as specified in the pull request, follow these steps: 1. **Review the Pull Request**: First, thoroughly review the changes specified in the pull request (https://github.com/bigshortbets/indexer/pull/75). Identify any new fields or changes in the event structure that need to be handled. 2. **Update Event Parsing**: Modify the event parsing logic to accommodate any new fields or changes in the event structure. 3. **Update Order Creation Logic**: Ensure that the new fields are correctly processed and stored in the `Order` entity. 4. **Test the Changes**: Write or update unit tests to ensure that the new fields are correctly handled and that the processor behaves as expected. Here is a concrete example of how you might update the `OrderCreatedEventProcessor`: ### Updated `OrderCreatedEventProcessor` Implementation ```typescript import { EventProcessor } from "../eventProcessor"; import { Store } from "@subsquid/typeorm-store"; import { ClosingOrder, Market, OpeningOrder, Order, OrderSide, OrderStatus, OrderType, } from "../../model"; import { AggregatedOrdersHandler } from "./aggregatedOrdersHandler"; import { DataHandlerContext, Block, Event, Call, } from "@subsquid/substrate-processor"; import * as events from "../../types/events"; import { encodeUserValue } from "../../utils/encodersUtils"; import { BigDecimal } from "@subsquid/big-decimal"; import { USDC_DECIMALS } from "../../utils"; export class OrderCreatedEventProcessor implements EventProcessor { getHandledEventName(): string { return "Market.OrderCreated"; } callName = "Market.create_order"; async process( ctx: DataHandlerContext, block: Block, event: Event, call: Call, ) { const orderCreatedEvent = events.market.orderCreated.v2; if (orderCreatedEvent.is(event)) { const parsedEvent = orderCreatedEvent.decode(event); const market = await ctx.store.get(Market, parsedEvent.market.toString()); const quantity = parsedEvent.quantity; let order: Order; order = new Order({ id: parsedEvent.orderId.toString(), market: market, price: BigDecimal(parsedEvent.price, USDC_DECIMALS), side: parsedEvent.side.__kind === "Long" ? OrderSide.LONG : OrderSide.SHORT, quantity: BigInt(quantity), initialQuantity: BigInt(quantity), who: encodeUserValue(parsedEvent.who), blockHeight: BigInt(block.header.height), // @ts-ignore timestamp: new Date(block.header.timestamp), status: OrderStatus.ACTIVE, type: parsedEvent.orderType.__kind === "Opening" ? new OpeningOrder({ type: "OpeningOrder" }) : new ClosingOrder({ type: "ClosingOrder", value: parsedEvent.orderType.value, }), // Add new fields here newField1: parsedEvent.newField1, // Example new field newField2: parsedEvent.newField2, // Example new field }); await ctx.store.save(order); await AggregatedOrdersHandler.addNewOrderToTheAggregatedOrders( ctx.store, order, ); } else { console.error("Unsupported spec"); } } } ``` ### Steps to Implement the Changes 1. **Identify New Fields**: Replace `newField1` and `newField2` with the actual new fields specified in the pull request. 2. **Update Event Types**: Ensure that the event types in `src/types/market/events.ts` are updated to include the new fields. 3. **Update Database Schema**: If the new fields require changes to the database schema, update the corresponding entity definitions and run migrations if necessary. 4. **Test the Processor**: Write or update unit tests to verify that the new fields are correctly processed and stored. By following these steps, you can ensure that the `OrderCreatedEventProcessor` is updated to handle new order creation events or additional data fields as specified in the pull request.
Changes on src/eventprocessor/market/orderFilledEventProcessor.ts To update the `OrderFilledEventProcessor` to handle new order filling events or additional data fields as specified in the pull request, follow these steps: 1. **Identify New Data Fields or Event Types**: Review the pull request (https://github.com/bigshortbets/indexer/pull/75) to understand what new data fields or event types need to be handled. 2. **Update Event Handling Logic**: Modify the existing logic to incorporate the new data fields or event types. This may involve decoding additional fields from the event, updating the database schema, or adding new processing logic. 3. **Test the Changes**: Ensure that the updated event processor works correctly with the new data fields or event types by writing and running tests. Here's a concrete example of how you might update the `OrderFilledEventProcessor` to handle a new field called `filledPrice` in the `OrderFilled` event: ### Updated Code ```typescript import { EventProcessor } from "../eventProcessor"; import { Store } from "@subsquid/typeorm-store"; import { Order, OrderStatus, Position, OrderSide } from "../../model"; import { AggregatedOrdersHandler } from "./aggregatedOrdersHandler"; import { DataHandlerContext, Event, Block, Call, } from "@subsquid/substrate-processor"; import * as events from "../../types/events"; export class OrderFilledEventProcessor implements EventProcessor { getHandledEventName(): string { return "Market.OrderFilled"; } async process( ctx: DataHandlerContext, block: Block, event: Event, ) { console.log("Order filled event"); const orderFilledEvent = events.market.orderFilled.v2; if (orderFilledEvent.is(event)) { let parsedEvent = orderFilledEvent.decode(event); let order = await ctx.store.findOne(Order, { where: { id: parsedEvent.orderId.toString() }, relations: { market: true }, }); if (order) { await AggregatedOrdersHandler.removeOrderFromAggregatedOrders( ctx.store, order, ); if (order.type.isTypeOf === "ClosingOrder") { let offsetingPositionId = order.type.value; let offsetingPosition = await ctx.store.findOne(Position, { where: { id: offsetingPositionId.toString() }, }); if (offsetingPosition) { const positionCreatedEvent = block.events.find( (element) => element.index < event.index && event.index - element.index <= 4 && element.callAddress?.toString() === event.callAddress?.toString() && element.name === "Market.PositionCreated", ); if (positionCreatedEvent) { let newPosition = await ctx.store.findOne(Position, { where: { id: positionCreatedEvent?.args.positionId.toString() }, }); if (newPosition) { if (order.side === OrderSide.LONG) { newPosition.createPriceLong = offsetingPosition.createPriceLong; } else { newPosition.createPriceShort = offsetingPosition.createPriceShort; } await ctx.store.save(newPosition); } } } else { console.warn("Position not found"); } } // Update the order with the new filledPrice field order.status = OrderStatus.COMPLETED; order.quantity = BigInt(0); order.filledPrice = parsedEvent.filledPrice; // Assuming filledPrice is part of the event await ctx.store.save(order); } } else { console.error("Unsupported spec"); } } } ``` ### Explanation 1. **Decode New Field**: The `filledPrice` field is decoded from the event and assigned to the `order` object. 2. **Save Updated Order**: The `order` object is updated with the new `filledPrice` field and saved to the database. ### Testing - **Unit Tests**: Write unit tests to ensure that the `OrderFilledEventProcessor` correctly handles events with the new `filledPrice` field. - **Integration Tests**: Run integration tests to verify that the entire event processing pipeline works as expected with the new data fields. By following these steps, you can ensure that the `OrderFilledEventProcessor` is updated to handle new order filling events or additional data fields as specified in the pull request.