diff --git a/indexer/packages/v4-protos/src/codegen/dydxprotocol/indexer/events/events.ts b/indexer/packages/v4-protos/src/codegen/dydxprotocol/indexer/events/events.ts index b497e0ec83..460f1d790d 100644 --- a/indexer/packages/v4-protos/src/codegen/dydxprotocol/indexer/events/events.ts +++ b/indexer/packages/v4-protos/src/codegen/dydxprotocol/indexer/events/events.ts @@ -1249,8 +1249,12 @@ export interface UpdateClobPairEventV1SDKType { /** * UpdatePerpetualEventV1 message contains all the information about an update * to a perpetual on the dYdX chain. + * Deprecated. See UpdatePerpetualEventV2 for the most up to date message + * for the event to update a perpetual. */ +/** @deprecated */ + export interface UpdatePerpetualEventV1 { /** * Unique Perpetual id. @@ -1288,8 +1292,12 @@ export interface UpdatePerpetualEventV1 { /** * UpdatePerpetualEventV1 message contains all the information about an update * to a perpetual on the dYdX chain. + * Deprecated. See UpdatePerpetualEventV2 for the most up to date message + * for the event to update a perpetual. */ +/** @deprecated */ + export interface UpdatePerpetualEventV1SDKType { /** * Unique Perpetual id. @@ -1324,6 +1332,90 @@ export interface UpdatePerpetualEventV1SDKType { liquidity_tier: number; } +/** + * UpdatePerpetualEventV2 message contains all the information about an update + * to a perpetual on the dYdX chain. + */ + +export interface UpdatePerpetualEventV2 { + /** + * Unique Perpetual id. + * Defined in perpetuals.perpetual + */ + id: number; + /** + * The name of the `Perpetual` (e.g. `BTC-USD`). + * Defined in perpetuals.perpetual + */ + + ticker: string; + /** + * Unique id of market param associated with this perpetual market. + * Defined in perpetuals.perpetual + */ + + marketId: number; + /** + * The exponent for converting an atomic amount (`size = 1`) + * to a full coin. For example, if `AtomicResolution = -8` + * then a `PerpetualPosition` with `size = 1e8` is equivalent to + * a position size of one full coin. + * Defined in perpetuals.perpetual + */ + + atomicResolution: number; + /** + * The liquidity_tier that this perpetual is associated with. + * Defined in perpetuals.perpetual + */ + + liquidityTier: number; + /** Market type of the perpetual. */ + + marketType: PerpetualMarketType; +} +/** + * UpdatePerpetualEventV2 message contains all the information about an update + * to a perpetual on the dYdX chain. + */ + +export interface UpdatePerpetualEventV2SDKType { + /** + * Unique Perpetual id. + * Defined in perpetuals.perpetual + */ + id: number; + /** + * The name of the `Perpetual` (e.g. `BTC-USD`). + * Defined in perpetuals.perpetual + */ + + ticker: string; + /** + * Unique id of market param associated with this perpetual market. + * Defined in perpetuals.perpetual + */ + + market_id: number; + /** + * The exponent for converting an atomic amount (`size = 1`) + * to a full coin. For example, if `AtomicResolution = -8` + * then a `PerpetualPosition` with `size = 1e8` is equivalent to + * a position size of one full coin. + * Defined in perpetuals.perpetual + */ + + atomic_resolution: number; + /** + * The liquidity_tier that this perpetual is associated with. + * Defined in perpetuals.perpetual + */ + + liquidity_tier: number; + /** Market type of the perpetual. */ + + market_type: PerpetualMarketTypeSDKType; +} /** * TradingRewardsEventV1 is communicates all trading rewards for all accounts * that receive trade rewards in the block. @@ -3485,6 +3577,101 @@ export const UpdatePerpetualEventV1 = { }; +function createBaseUpdatePerpetualEventV2(): UpdatePerpetualEventV2 { + return { + id: 0, + ticker: "", + marketId: 0, + atomicResolution: 0, + liquidityTier: 0, + marketType: 0 + }; +} + +export const UpdatePerpetualEventV2 = { + encode(message: UpdatePerpetualEventV2, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer { + if (message.id !== 0) { + writer.uint32(8).uint32(message.id); + } + + if (message.ticker !== "") { + writer.uint32(18).string(message.ticker); + } + + if (message.marketId !== 0) { + writer.uint32(24).uint32(message.marketId); + } + + if (message.atomicResolution !== 0) { + writer.uint32(32).sint32(message.atomicResolution); + } + + if (message.liquidityTier !== 0) { + writer.uint32(40).uint32(message.liquidityTier); + } + + if (message.marketType !== 0) { + writer.uint32(48).int32(message.marketType); + } + + return writer; + }, + + decode(input: _m0.Reader | Uint8Array, length?: number): UpdatePerpetualEventV2 { + const reader = input instanceof _m0.Reader ? input : new _m0.Reader(input); + let end = length === undefined ? reader.len : reader.pos + length; + const message = createBaseUpdatePerpetualEventV2(); + + while (reader.pos < end) { + const tag = reader.uint32(); + + switch (tag >>> 3) { + case 1: + message.id = reader.uint32(); + break; + + case 2: + message.ticker = reader.string(); + break; + + case 3: + message.marketId = reader.uint32(); + break; + + case 4: + message.atomicResolution = reader.sint32(); + break; + + case 5: + message.liquidityTier = reader.uint32(); + break; + + case 6: + message.marketType = (reader.int32() as any); + break; + + default: + reader.skipType(tag & 7); + break; + } + } + + return message; + }, + + fromPartial(object: DeepPartial): UpdatePerpetualEventV2 { + const message = createBaseUpdatePerpetualEventV2(); + message.id = object.id ?? 0; + message.ticker = object.ticker ?? ""; + message.marketId = object.marketId ?? 0; + message.atomicResolution = object.atomicResolution ?? 0; + message.liquidityTier = object.liquidityTier ?? 0; + message.marketType = object.marketType ?? 0; + return message; + } + +}; + function createBaseTradingRewardsEventV1(): TradingRewardsEventV1 { return { tradingRewards: [] diff --git a/indexer/services/ender/__tests__/handlers/update-perpetual-handler.test.ts b/indexer/services/ender/__tests__/handlers/update-perpetual-handler.test.ts index f6d67cfcdc..9fdbc43acb 100644 --- a/indexer/services/ender/__tests__/handlers/update-perpetual-handler.test.ts +++ b/indexer/services/ender/__tests__/handlers/update-perpetual-handler.test.ts @@ -12,17 +12,20 @@ import { defaultPreviousHeight, defaultTime, defaultTxHash, - defaultUpdatePerpetualEvent, + defaultUpdatePerpetualEventV1, + defaultUpdatePerpetualEventV2, } from '../helpers/constants'; import { IndexerTendermintBlock, IndexerTendermintEvent, Timestamp, UpdatePerpetualEventV1, + UpdatePerpetualEventV2, } from '@dydxprotocol-indexer/v4-protos'; import { createIndexerTendermintBlock, createIndexerTendermintEvent, + eventPerpetualMarketTypeToIndexerPerpetualMarketType, expectPerpetualMarketKafkaMessage, } from '../helpers/indexer-proto-helpers'; import { DydxIndexerSubtypes } from '../../src/lib/types'; @@ -57,14 +60,29 @@ describe('update-perpetual-handler', () => { jest.resetAllMocks(); }); - describe('getParallelizationIds', () => { + describe.each([ + [ + 'UpdatePerpetualEventV1', + UpdatePerpetualEventV1.encode(defaultUpdatePerpetualEventV1).finish(), + defaultUpdatePerpetualEventV1, + ], + [ + 'UpdatePerpetualEventV2', + UpdatePerpetualEventV2.encode(defaultUpdatePerpetualEventV2).finish(), + defaultUpdatePerpetualEventV2, + ], + ])('%s', ( + _name: string, + updatePerpetualEventBytes: Uint8Array, + event: UpdatePerpetualEventV1 | UpdatePerpetualEventV2, + ) => { it('returns the correct parallelization ids', () => { const transactionIndex: number = 0; const eventIndex: number = 0; const indexerTendermintEvent: IndexerTendermintEvent = createIndexerTendermintEvent( DydxIndexerSubtypes.UPDATE_PERPETUAL, - UpdatePerpetualEventV1.encode(defaultUpdatePerpetualEvent).finish(), + updatePerpetualEventBytes, transactionIndex, eventIndex, ); @@ -80,51 +98,56 @@ describe('update-perpetual-handler', () => { 0, indexerTendermintEvent, 0, - defaultUpdatePerpetualEvent, + event, ); expect(handler.getParallelizationIds()).toEqual([]); }); - }); - it('updates an existing perpetual market', async () => { - const transactionIndex: number = 0; - const kafkaMessage: KafkaMessage = createKafkaMessageFromUpdatePerpetualEvent({ - updatePerpetualEvent: defaultUpdatePerpetualEvent, - transactionIndex, - height: defaultHeight, - time: defaultTime, - txHash: defaultTxHash, - }); - const producerSendMock: jest.SpyInstance = jest.spyOn(producer, 'send'); - await onMessage(kafkaMessage); + it('updates an existing perpetual market', async () => { + const transactionIndex: number = 0; + const kafkaMessage: KafkaMessage = createKafkaMessageFromUpdatePerpetualEvent({ + updatePerpetualEventBytes, + transactionIndex, + height: defaultHeight, + time: defaultTime, + txHash: defaultTxHash, + }); + const producerSendMock: jest.SpyInstance = jest.spyOn(producer, 'send'); + await onMessage(kafkaMessage); + + const perpetualMarket: + PerpetualMarketFromDatabase | undefined = await PerpetualMarketTable.findById( + event.id.toString(), + ); - const perpetualMarket: - PerpetualMarketFromDatabase | undefined = await PerpetualMarketTable.findById( - defaultUpdatePerpetualEvent.id.toString(), - ); - expect(perpetualMarket).toEqual(expect.objectContaining({ - id: defaultUpdatePerpetualEvent.id.toString(), - ticker: defaultUpdatePerpetualEvent.ticker, - marketId: defaultUpdatePerpetualEvent.marketId, - atomicResolution: defaultUpdatePerpetualEvent.atomicResolution, - liquidityTierId: defaultUpdatePerpetualEvent.liquidityTier, - })); - expect(perpetualMarket).toEqual( - perpetualMarketRefresher.getPerpetualMarketFromId( - defaultUpdatePerpetualEvent.id.toString())); - expectPerpetualMarketKafkaMessage(producerSendMock, [perpetualMarket!]); + expect(perpetualMarket).toEqual(expect.objectContaining({ + id: event.id.toString(), + ticker: event.ticker, + marketId: event.marketId, + atomicResolution: event.atomicResolution, + liquidityTierId: event.liquidityTier, + // Add V2-specific field expectations when testing V2 events + ...('marketType' in event && { + marketType: eventPerpetualMarketTypeToIndexerPerpetualMarketType(event.marketType), + }), + })); + expect(perpetualMarket).toEqual( + perpetualMarketRefresher.getPerpetualMarketFromId( + event.id.toString())); + expectPerpetualMarketKafkaMessage(producerSendMock, [perpetualMarket!]); + }); }); }); function createKafkaMessageFromUpdatePerpetualEvent({ - updatePerpetualEvent, + updatePerpetualEventBytes, transactionIndex, height, time, txHash, }: { - updatePerpetualEvent: UpdatePerpetualEventV1, + updatePerpetualEventBytes: Uint8Array, transactionIndex: number, height: number, time: Timestamp, @@ -134,7 +157,7 @@ function createKafkaMessageFromUpdatePerpetualEvent({ events.push( createIndexerTendermintEvent( DydxIndexerSubtypes.UPDATE_PERPETUAL, - UpdatePerpetualEventV1.encode(updatePerpetualEvent).finish(), + updatePerpetualEventBytes, transactionIndex, 0, ), diff --git a/indexer/services/ender/__tests__/helpers/constants.ts b/indexer/services/ender/__tests__/helpers/constants.ts index cb841d2d82..c871f589ba 100644 --- a/indexer/services/ender/__tests__/helpers/constants.ts +++ b/indexer/services/ender/__tests__/helpers/constants.ts @@ -35,6 +35,7 @@ import { TransferEventV1, UpdateClobPairEventV1, UpdatePerpetualEventV1, + UpdatePerpetualEventV2, OpenInterestUpdateEventV1, OpenInterestUpdate, } from '@dydxprotocol-indexer/v4-protos'; @@ -191,7 +192,7 @@ export const defaultOpenInterestUpdateEvent: OpenInterestUpdateEventV1 = { openInterestUpdates: [defaultOpenInterestUpdate1, defaultOpenInterestUpdate2], }; -export const defaultUpdatePerpetualEvent: UpdatePerpetualEventV1 = { +export const defaultUpdatePerpetualEventV1: UpdatePerpetualEventV1 = { id: 0, ticker: 'BTC-USD2', marketId: 1, @@ -199,6 +200,15 @@ export const defaultUpdatePerpetualEvent: UpdatePerpetualEventV1 = { liquidityTier: 1, }; +export const defaultUpdatePerpetualEventV2: UpdatePerpetualEventV2 = { + id: 0, + ticker: 'BTC-USD2', + marketId: 1, + atomicResolution: -8, + liquidityTier: 1, + marketType: PerpetualMarketType.PERPETUAL_MARKET_TYPE_CROSS, +}; + export const defaultUpdateClobPairEvent: UpdateClobPairEventV1 = { clobPairId: 1, status: ClobPairStatus.CLOB_PAIR_STATUS_ACTIVE, diff --git a/indexer/services/ender/__tests__/helpers/indexer-proto-helpers.ts b/indexer/services/ender/__tests__/helpers/indexer-proto-helpers.ts index 76cc04d19c..d0fe5ea32e 100644 --- a/indexer/services/ender/__tests__/helpers/indexer-proto-helpers.ts +++ b/indexer/services/ender/__tests__/helpers/indexer-proto-helpers.ts @@ -971,7 +971,7 @@ export function expectPerpetualMarketV2( })); } -function eventPerpetualMarketTypeToIndexerPerpetualMarketType( +export function eventPerpetualMarketTypeToIndexerPerpetualMarketType( perpetualMarketType: PerpetualMarketType, ): string { switch (perpetualMarketType) { diff --git a/indexer/services/ender/__tests__/validators/update-perpetual-validator.test.ts b/indexer/services/ender/__tests__/validators/update-perpetual-validator.test.ts index 8ba7128494..5cb6bb4c14 100644 --- a/indexer/services/ender/__tests__/validators/update-perpetual-validator.test.ts +++ b/indexer/services/ender/__tests__/validators/update-perpetual-validator.test.ts @@ -3,13 +3,15 @@ import { IndexerTendermintBlock, IndexerTendermintEvent, UpdatePerpetualEventV1, + UpdatePerpetualEventV2, } from '@dydxprotocol-indexer/v4-protos'; import { dbHelpers, testMocks, perpetualMarketRefresher, } from '@dydxprotocol-indexer/postgres'; import { DydxIndexerSubtypes } from '../../src/lib/types'; import { - defaultUpdatePerpetualEvent, + defaultUpdatePerpetualEventV1, + defaultUpdatePerpetualEventV2, defaultHeight, defaultTime, defaultTxHash, @@ -42,11 +44,26 @@ describe('update-perpetual-validator', () => { await dbHelpers.teardown(); }); - describe('validate', () => { + describe.each([ + [ + 'UpdatePerpetualEventV1', + UpdatePerpetualEventV1.encode(defaultUpdatePerpetualEventV1).finish(), + defaultUpdatePerpetualEventV1, + ], + [ + 'PerpetualMarketCreateEventV2', + UpdatePerpetualEventV2.encode(defaultUpdatePerpetualEventV2).finish(), + defaultUpdatePerpetualEventV2, + ], + ])('%s', ( + _name: string, + updatePerpetualEventBytes: Uint8Array, + event: UpdatePerpetualEventV1 | UpdatePerpetualEventV2, + ) => { it('does not throw error on valid perpetual market create event', () => { const validator: UpdatePerpetualValidator = new UpdatePerpetualValidator( - defaultUpdatePerpetualEvent, - createBlock(defaultUpdatePerpetualEvent), + event, + createBlock(updatePerpetualEventBytes), 0, ); @@ -57,10 +74,10 @@ describe('update-perpetual-validator', () => { it('throws error if id does not correspond to an existing perpetual market', () => { const validator: UpdatePerpetualValidator = new UpdatePerpetualValidator( { - ...defaultUpdatePerpetualEvent, + ...event, id: 20, }, - createBlock(defaultUpdatePerpetualEvent), + createBlock(updatePerpetualEventBytes), 0, ); @@ -72,11 +89,11 @@ describe('update-perpetual-validator', () => { }); function createBlock( - updatePerpetualEvent: UpdatePerpetualEventV1, + updatePerpetualEventBytes: Uint8Array, ): IndexerTendermintBlock { const event: IndexerTendermintEvent = createIndexerTendermintEvent( DydxIndexerSubtypes.UPDATE_PERPETUAL, - UpdatePerpetualEventV1.encode(updatePerpetualEvent).finish(), + updatePerpetualEventBytes, 0, 0, ); diff --git a/indexer/services/ender/src/handlers/update-perpetual-handler.ts b/indexer/services/ender/src/handlers/update-perpetual-handler.ts index d17d48e130..abaf22a044 100644 --- a/indexer/services/ender/src/handlers/update-perpetual-handler.ts +++ b/indexer/services/ender/src/handlers/update-perpetual-handler.ts @@ -4,7 +4,7 @@ import { perpetualMarketRefresher, PerpetualMarketModel, } from '@dydxprotocol-indexer/postgres'; -import { UpdatePerpetualEventV1 } from '@dydxprotocol-indexer/v4-protos'; +import { UpdatePerpetualEventV1, UpdatePerpetualEventV2 } from '@dydxprotocol-indexer/v4-protos'; import * as pg from 'pg'; import config from '../config'; @@ -12,8 +12,9 @@ import { generatePerpetualMarketMessage } from '../helpers/kafka-helper'; import { ConsolidatedKafkaEvent } from '../lib/types'; import { Handler } from './handler'; -export class UpdatePerpetualHandler extends Handler { - eventType: string = 'UpdatePerpetualEventV1'; +export class UpdatePerpetualHandler extends Handler< + UpdatePerpetualEventV1 | UpdatePerpetualEventV2> { + eventType: string = 'UpdatePerpetualEvent'; public getParallelizationIds(): string[] { return []; diff --git a/indexer/services/ender/src/helpers/postgres/postgres-functions.ts b/indexer/services/ender/src/helpers/postgres/postgres-functions.ts index 9a82c0eeff..aaae9616ce 100644 --- a/indexer/services/ender/src/helpers/postgres/postgres-functions.ts +++ b/indexer/services/ender/src/helpers/postgres/postgres-functions.ts @@ -44,7 +44,8 @@ const HANDLER_SCRIPTS: string[] = [ 'dydx_trading_rewards_handler.sql', 'dydx_transfer_handler.sql', 'dydx_update_clob_pair_handler.sql', - 'dydx_update_perpetual_handler.sql', + 'dydx_update_perpetual_v1_handler.sql', + 'dydx_update_perpetual_v2_handler.sql', 'dydx_vault_upsert_handler.sql', ]; diff --git a/indexer/services/ender/src/lib/block-processor.ts b/indexer/services/ender/src/lib/block-processor.ts index 6051425b8e..f00a5cd061 100644 --- a/indexer/services/ender/src/lib/block-processor.ts +++ b/indexer/services/ender/src/lib/block-processor.ts @@ -51,6 +51,7 @@ const TXN_EVENT_SUBTYPE_VERSION_TO_VALIDATOR_MAPPING: Record'version')::int + WHEN 1 THEN + rval[i] = dydx_update_perpetual_v1_handler(event_data); + WHEN 2 THEN + rval[i] = dydx_update_perpetual_v2_handler(event_data); + ELSE + NULL; + END CASE; WHEN '"update_clob_pair"'::jsonb THEN rval[i] = dydx_update_clob_pair_handler(event_data); WHEN '"funding_values"'::jsonb THEN diff --git a/indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v1_handler.sql b/indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v1_handler.sql new file mode 100644 index 0000000000..1bcb60354a --- /dev/null +++ b/indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v1_handler.sql @@ -0,0 +1,40 @@ +CREATE OR REPLACE FUNCTION dydx_update_perpetual_v1_handler(event_data jsonb) RETURNS jsonb AS $$ +/** + Note: This is a deprecated handler, see `dydx_update_perpetual_v2_handler` for the latest handler. + Parameters: + - event_data: The 'data' field of the IndexerTendermintEvent (https://github.com/dydxprotocol/v4-chain/blob/9ed26bd/proto/dydxprotocol/indexer/indexer_manager/event.proto#L25) + converted to JSON format. Conversion to JSON is expected to be done by JSON.stringify. + Returns: JSON object containing fields: + - perpetual_market: The updated perpetual market in perpetual-market-model format (https://github.com/dydxprotocol/v4-chain/blob/9ed26bd/indexer/packages/postgres/src/models/perpetual-market-model.ts). + + (Note that no text should exist before the function declaration to ensure that exception line numbers are correct.) +*/ +DECLARE + perpetual_market_id bigint; + perpetual_market_record perpetual_markets%ROWTYPE; +BEGIN + perpetual_market_id = (event_data->'id')::bigint; + perpetual_market_record."ticker" = event_data->>'ticker'; + perpetual_market_record."marketId" = (event_data->'marketId')::integer; + perpetual_market_record."atomicResolution" = (event_data->'atomicResolution')::integer; + perpetual_market_record."liquidityTierId" = (event_data->'liquidityTier')::integer; + + UPDATE perpetual_markets + SET + "ticker" = perpetual_market_record."ticker", + "marketId" = perpetual_market_record."marketId", + "atomicResolution" = perpetual_market_record."atomicResolution", + "liquidityTierId" = perpetual_market_record."liquidityTierId" + WHERE "id" = perpetual_market_id + RETURNING * INTO perpetual_market_record; + + IF NOT FOUND THEN + RAISE EXCEPTION 'Could not find perpetual market with corresponding id %', perpetual_market_id; + END IF; + + RETURN jsonb_build_object( + 'perpetual_market', + dydx_to_jsonb(perpetual_market_record) + ); +END; +$$ LANGUAGE plpgsql; \ No newline at end of file diff --git a/indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v2_handler.sql b/indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v2_handler.sql new file mode 100644 index 0000000000..202ac39572 --- /dev/null +++ b/indexer/services/ender/src/scripts/handlers/dydx_update_perpetual_v2_handler.sql @@ -0,0 +1,41 @@ +CREATE OR REPLACE FUNCTION dydx_update_perpetual_v2_handler(event_data jsonb) RETURNS jsonb AS $$ +/** + Parameters: + - event_data: The 'data' field of the IndexerTendermintEvent (https://github.com/dydxprotocol/v4-chain/blob/9ed26bd/proto/dydxprotocol/indexer/indexer_manager/event.proto#L25) + converted to JSON format. Conversion to JSON is expected to be done by JSON.stringify. + Returns: JSON object containing fields: + - perpetual_market: The updated perpetual market in perpetual-market-model format (https://github.com/dydxprotocol/v4-chain/blob/9ed26bd/indexer/packages/postgres/src/models/perpetual-market-model.ts). + + (Note that no text should exist before the function declaration to ensure that exception line numbers are correct.) +*/ +DECLARE + perpetual_market_id bigint; + perpetual_market_record perpetual_markets%ROWTYPE; +BEGIN + perpetual_market_id = (event_data->'id')::bigint; + perpetual_market_record."ticker" = event_data->>'ticker'; + perpetual_market_record."marketId" = (event_data->'marketId')::integer; + perpetual_market_record."atomicResolution" = (event_data->'atomicResolution')::integer; + perpetual_market_record."liquidityTierId" = (event_data->'liquidityTier')::integer; + perpetual_market_record."marketType" = dydx_protocol_market_type_to_perpetual_market_type(event_data->'marketType'); + + UPDATE perpetual_markets + SET + "ticker" = perpetual_market_record."ticker", + "marketId" = perpetual_market_record."marketId", + "atomicResolution" = perpetual_market_record."atomicResolution", + "liquidityTierId" = perpetual_market_record."liquidityTierId", + "marketType" = perpetual_market_record."marketType" + WHERE "id" = perpetual_market_id + RETURNING * INTO perpetual_market_record; + + IF NOT FOUND THEN + RAISE EXCEPTION 'Could not find perpetual market with corresponding id %', perpetual_market_id; + END IF; + + RETURN jsonb_build_object( + 'perpetual_market', + dydx_to_jsonb(perpetual_market_record) + ); +END; +$$ LANGUAGE plpgsql; \ No newline at end of file diff --git a/indexer/services/ender/src/validators/update-perpetual-validator.ts b/indexer/services/ender/src/validators/update-perpetual-validator.ts index 25caf65123..4bc50fe744 100644 --- a/indexer/services/ender/src/validators/update-perpetual-validator.ts +++ b/indexer/services/ender/src/validators/update-perpetual-validator.ts @@ -1,11 +1,13 @@ import { perpetualMarketRefresher } from '@dydxprotocol-indexer/postgres'; -import { IndexerTendermintEvent, UpdatePerpetualEventV1 } from '@dydxprotocol-indexer/v4-protos'; +import { IndexerTendermintEvent, UpdatePerpetualEventV1, UpdatePerpetualEventV2 } from '@dydxprotocol-indexer/v4-protos'; import { Handler } from '../handlers/handler'; import { UpdatePerpetualHandler } from '../handlers/update-perpetual-handler'; import { Validator } from './validator'; -export class UpdatePerpetualValidator extends Validator { +export class UpdatePerpetualValidator extends Validator< + UpdatePerpetualEventV1 | UpdatePerpetualEventV2 +> { public validate(): void { if (perpetualMarketRefresher.getPerpetualMarketFromId(this.event.id.toString()) === undefined) { return this.logAndThrowParseMessageError( diff --git a/proto/dydxprotocol/indexer/events/events.proto b/proto/dydxprotocol/indexer/events/events.proto index ed555d527e..3568673e7d 100644 --- a/proto/dydxprotocol/indexer/events/events.proto +++ b/proto/dydxprotocol/indexer/events/events.proto @@ -486,7 +486,37 @@ message UpdateClobPairEventV1 { // UpdatePerpetualEventV1 message contains all the information about an update // to a perpetual on the dYdX chain. +// Deprecated. See UpdatePerpetualEventV2 for the most up to date message +// for the event to update a perpetual. message UpdatePerpetualEventV1 { + option deprecated = true; + // Unique Perpetual id. + // Defined in perpetuals.perpetual + uint32 id = 1; + + // The name of the `Perpetual` (e.g. `BTC-USD`). + // Defined in perpetuals.perpetual + string ticker = 2; + + // Unique id of market param associated with this perpetual market. + // Defined in perpetuals.perpetual + uint32 market_id = 3; + + // The exponent for converting an atomic amount (`size = 1`) + // to a full coin. For example, if `AtomicResolution = -8` + // then a `PerpetualPosition` with `size = 1e8` is equivalent to + // a position size of one full coin. + // Defined in perpetuals.perpetual + sint32 atomic_resolution = 4; + + // The liquidity_tier that this perpetual is associated with. + // Defined in perpetuals.perpetual + uint32 liquidity_tier = 5; +} + +// UpdatePerpetualEventV2 message contains all the information about an update +// to a perpetual on the dYdX chain. +message UpdatePerpetualEventV2 { // Unique Perpetual id. // Defined in perpetuals.perpetual uint32 id = 1; @@ -509,6 +539,9 @@ message UpdatePerpetualEventV1 { // The liquidity_tier that this perpetual is associated with. // Defined in perpetuals.perpetual uint32 liquidity_tier = 5; + + // Market type of the perpetual. + dydxprotocol.indexer.protocol.v1.PerpetualMarketType market_type = 6; } // TradingRewardsEventV1 is communicates all trading rewards for all accounts diff --git a/protocol/app/app.go b/protocol/app/app.go index 042bac91ea..c637f8d755 100644 --- a/protocol/app/app.go +++ b/protocol/app/app.go @@ -1238,6 +1238,7 @@ func New( []string{ lib.GovModuleAddress.String(), }, + app.IndexerEventManager, app.PricesKeeper, app.ClobKeeper, &app.MarketMapKeeper, diff --git a/protocol/indexer/events/constants.go b/protocol/indexer/events/constants.go index 0292aa427e..f0a77cc1dd 100644 --- a/protocol/indexer/events/constants.go +++ b/protocol/indexer/events/constants.go @@ -34,7 +34,7 @@ const ( AssetEventVersion uint32 = 1 PerpetualMarketEventVersion uint32 = 2 LiquidityTierEventVersion uint32 = 2 - UpdatePerpetualEventVersion uint32 = 1 + UpdatePerpetualEventVersion uint32 = 2 UpdateClobPairEventVersion uint32 = 1 DeleveragingEventVersion uint32 = 1 TradingRewardVersion uint32 = 1 diff --git a/protocol/indexer/events/events.pb.go b/protocol/indexer/events/events.pb.go index 4c5fed6d9e..c7a34d5dab 100644 --- a/protocol/indexer/events/events.pb.go +++ b/protocol/indexer/events/events.pb.go @@ -2156,6 +2156,10 @@ func (m *UpdateClobPairEventV1) GetStepBaseQuantums() uint64 { // UpdatePerpetualEventV1 message contains all the information about an update // to a perpetual on the dYdX chain. +// Deprecated. See UpdatePerpetualEventV2 for the most up to date message +// for the event to update a perpetual. +// +// Deprecated: Do not use. type UpdatePerpetualEventV1 struct { // Unique Perpetual id. // Defined in perpetuals.perpetual @@ -2245,6 +2249,106 @@ func (m *UpdatePerpetualEventV1) GetLiquidityTier() uint32 { return 0 } +// UpdatePerpetualEventV2 message contains all the information about an update +// to a perpetual on the dYdX chain. +type UpdatePerpetualEventV2 struct { + // Unique Perpetual id. + // Defined in perpetuals.perpetual + Id uint32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` + // The name of the `Perpetual` (e.g. `BTC-USD`). + // Defined in perpetuals.perpetual + Ticker string `protobuf:"bytes,2,opt,name=ticker,proto3" json:"ticker,omitempty"` + // Unique id of market param associated with this perpetual market. + // Defined in perpetuals.perpetual + MarketId uint32 `protobuf:"varint,3,opt,name=market_id,json=marketId,proto3" json:"market_id,omitempty"` + // The exponent for converting an atomic amount (`size = 1`) + // to a full coin. For example, if `AtomicResolution = -8` + // then a `PerpetualPosition` with `size = 1e8` is equivalent to + // a position size of one full coin. + // Defined in perpetuals.perpetual + AtomicResolution int32 `protobuf:"zigzag32,4,opt,name=atomic_resolution,json=atomicResolution,proto3" json:"atomic_resolution,omitempty"` + // The liquidity_tier that this perpetual is associated with. + // Defined in perpetuals.perpetual + LiquidityTier uint32 `protobuf:"varint,5,opt,name=liquidity_tier,json=liquidityTier,proto3" json:"liquidity_tier,omitempty"` + // Market type of the perpetual. + MarketType types.PerpetualMarketType `protobuf:"varint,6,opt,name=market_type,json=marketType,proto3,enum=dydxprotocol.indexer.protocol.v1.PerpetualMarketType" json:"market_type,omitempty"` +} + +func (m *UpdatePerpetualEventV2) Reset() { *m = UpdatePerpetualEventV2{} } +func (m *UpdatePerpetualEventV2) String() string { return proto.CompactTextString(m) } +func (*UpdatePerpetualEventV2) ProtoMessage() {} +func (*UpdatePerpetualEventV2) Descriptor() ([]byte, []int) { + return fileDescriptor_6331dfb59c6fd2bb, []int{20} +} +func (m *UpdatePerpetualEventV2) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) +} +func (m *UpdatePerpetualEventV2) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + if deterministic { + return xxx_messageInfo_UpdatePerpetualEventV2.Marshal(b, m, deterministic) + } else { + b = b[:cap(b)] + n, err := m.MarshalToSizedBuffer(b) + if err != nil { + return nil, err + } + return b[:n], nil + } +} +func (m *UpdatePerpetualEventV2) XXX_Merge(src proto.Message) { + xxx_messageInfo_UpdatePerpetualEventV2.Merge(m, src) +} +func (m *UpdatePerpetualEventV2) XXX_Size() int { + return m.Size() +} +func (m *UpdatePerpetualEventV2) XXX_DiscardUnknown() { + xxx_messageInfo_UpdatePerpetualEventV2.DiscardUnknown(m) +} + +var xxx_messageInfo_UpdatePerpetualEventV2 proto.InternalMessageInfo + +func (m *UpdatePerpetualEventV2) GetId() uint32 { + if m != nil { + return m.Id + } + return 0 +} + +func (m *UpdatePerpetualEventV2) GetTicker() string { + if m != nil { + return m.Ticker + } + return "" +} + +func (m *UpdatePerpetualEventV2) GetMarketId() uint32 { + if m != nil { + return m.MarketId + } + return 0 +} + +func (m *UpdatePerpetualEventV2) GetAtomicResolution() int32 { + if m != nil { + return m.AtomicResolution + } + return 0 +} + +func (m *UpdatePerpetualEventV2) GetLiquidityTier() uint32 { + if m != nil { + return m.LiquidityTier + } + return 0 +} + +func (m *UpdatePerpetualEventV2) GetMarketType() types.PerpetualMarketType { + if m != nil { + return m.MarketType + } + return types.PerpetualMarketType_PERPETUAL_MARKET_TYPE_UNSPECIFIED +} + // TradingRewardsEventV1 is communicates all trading rewards for all accounts // that receive trade rewards in the block. type TradingRewardsEventV1 struct { @@ -2256,7 +2360,7 @@ func (m *TradingRewardsEventV1) Reset() { *m = TradingRewardsEventV1{} } func (m *TradingRewardsEventV1) String() string { return proto.CompactTextString(m) } func (*TradingRewardsEventV1) ProtoMessage() {} func (*TradingRewardsEventV1) Descriptor() ([]byte, []int) { - return fileDescriptor_6331dfb59c6fd2bb, []int{20} + return fileDescriptor_6331dfb59c6fd2bb, []int{21} } func (m *TradingRewardsEventV1) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2306,7 +2410,7 @@ func (m *AddressTradingReward) Reset() { *m = AddressTradingReward{} } func (m *AddressTradingReward) String() string { return proto.CompactTextString(m) } func (*AddressTradingReward) ProtoMessage() {} func (*AddressTradingReward) Descriptor() ([]byte, []int) { - return fileDescriptor_6331dfb59c6fd2bb, []int{21} + return fileDescriptor_6331dfb59c6fd2bb, []int{22} } func (m *AddressTradingReward) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2354,7 +2458,7 @@ func (m *OpenInterestUpdateEventV1) Reset() { *m = OpenInterestUpdateEve func (m *OpenInterestUpdateEventV1) String() string { return proto.CompactTextString(m) } func (*OpenInterestUpdateEventV1) ProtoMessage() {} func (*OpenInterestUpdateEventV1) Descriptor() ([]byte, []int) { - return fileDescriptor_6331dfb59c6fd2bb, []int{22} + return fileDescriptor_6331dfb59c6fd2bb, []int{23} } func (m *OpenInterestUpdateEventV1) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2404,7 +2508,7 @@ func (m *OpenInterestUpdate) Reset() { *m = OpenInterestUpdate{} } func (m *OpenInterestUpdate) String() string { return proto.CompactTextString(m) } func (*OpenInterestUpdate) ProtoMessage() {} func (*OpenInterestUpdate) Descriptor() ([]byte, []int) { - return fileDescriptor_6331dfb59c6fd2bb, []int{23} + return fileDescriptor_6331dfb59c6fd2bb, []int{24} } func (m *OpenInterestUpdate) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2470,7 +2574,7 @@ func (m *LiquidityTierUpsertEventV2) Reset() { *m = LiquidityTierUpsertE func (m *LiquidityTierUpsertEventV2) String() string { return proto.CompactTextString(m) } func (*LiquidityTierUpsertEventV2) ProtoMessage() {} func (*LiquidityTierUpsertEventV2) Descriptor() ([]byte, []int) { - return fileDescriptor_6331dfb59c6fd2bb, []int{24} + return fileDescriptor_6331dfb59c6fd2bb, []int{25} } func (m *LiquidityTierUpsertEventV2) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2561,7 +2665,7 @@ func (m *RegisterAffiliateEventV1) Reset() { *m = RegisterAffiliateEvent func (m *RegisterAffiliateEventV1) String() string { return proto.CompactTextString(m) } func (*RegisterAffiliateEventV1) ProtoMessage() {} func (*RegisterAffiliateEventV1) Descriptor() ([]byte, []int) { - return fileDescriptor_6331dfb59c6fd2bb, []int{25} + return fileDescriptor_6331dfb59c6fd2bb, []int{26} } func (m *RegisterAffiliateEventV1) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2618,7 +2722,7 @@ func (m *UpsertVaultEventV1) Reset() { *m = UpsertVaultEventV1{} } func (m *UpsertVaultEventV1) String() string { return proto.CompactTextString(m) } func (*UpsertVaultEventV1) ProtoMessage() {} func (*UpsertVaultEventV1) Descriptor() ([]byte, []int) { - return fileDescriptor_6331dfb59c6fd2bb, []int{26} + return fileDescriptor_6331dfb59c6fd2bb, []int{27} } func (m *UpsertVaultEventV1) XXX_Unmarshal(b []byte) error { return m.Unmarshal(b) @@ -2696,6 +2800,7 @@ func init() { proto.RegisterType((*LiquidityTierUpsertEventV1)(nil), "dydxprotocol.indexer.events.LiquidityTierUpsertEventV1") proto.RegisterType((*UpdateClobPairEventV1)(nil), "dydxprotocol.indexer.events.UpdateClobPairEventV1") proto.RegisterType((*UpdatePerpetualEventV1)(nil), "dydxprotocol.indexer.events.UpdatePerpetualEventV1") + proto.RegisterType((*UpdatePerpetualEventV2)(nil), "dydxprotocol.indexer.events.UpdatePerpetualEventV2") proto.RegisterType((*TradingRewardsEventV1)(nil), "dydxprotocol.indexer.events.TradingRewardsEventV1") proto.RegisterType((*AddressTradingReward)(nil), "dydxprotocol.indexer.events.AddressTradingReward") proto.RegisterType((*OpenInterestUpdateEventV1)(nil), "dydxprotocol.indexer.events.OpenInterestUpdateEventV1") @@ -2710,160 +2815,161 @@ func init() { } var fileDescriptor_6331dfb59c6fd2bb = []byte{ - // 2441 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x6f, 0x24, 0x47, - 0x15, 0x77, 0xcf, 0x8c, 0xc7, 0xe3, 0x37, 0x1e, 0xef, 0x4c, 0xed, 0xd8, 0x3b, 0xb6, 0x61, 0x77, - 0x69, 0x09, 0x69, 0x95, 0x8f, 0xf1, 0xae, 0x49, 0xa2, 0x28, 0x07, 0x84, 0xc7, 0x1f, 0xf1, 0x58, - 0xb6, 0x77, 0xd2, 0xfe, 0x48, 0xb2, 0xa0, 0x34, 0xe5, 0xee, 0x9a, 0x71, 0xc9, 0xfd, 0xb5, 0x5d, - 0x3d, 0xde, 0x78, 0x11, 0x37, 0x44, 0x38, 0x20, 0x81, 0x84, 0x38, 0x70, 0x40, 0xe2, 0xc2, 0x25, - 0x12, 0x07, 0x24, 0xc4, 0x8d, 0x03, 0xe2, 0x92, 0x1b, 0x11, 0x27, 0x04, 0x52, 0x84, 0x92, 0x03, - 0xff, 0x06, 0xaa, 0x8f, 0xee, 0xf9, 0x1e, 0xcf, 0xc6, 0x8e, 0x84, 0x10, 0x27, 0x4f, 0xbd, 0x57, - 0xef, 0xf7, 0x5e, 0xbd, 0xf7, 0xaa, 0xea, 0xd5, 0x6b, 0xc3, 0x03, 0xfb, 0xd2, 0xfe, 0x30, 0x08, - 0xfd, 0xc8, 0xb7, 0x7c, 0x67, 0x95, 0x7a, 0x36, 0xf9, 0x90, 0x84, 0xab, 0xe4, 0x82, 0x78, 0x11, - 0x53, 0x7f, 0xaa, 0x82, 0x8d, 0x56, 0xba, 0x67, 0x56, 0xd5, 0xcc, 0xaa, 0x9c, 0xb2, 0xbc, 0x64, - 0xf9, 0xcc, 0xf5, 0x99, 0x29, 0xf8, 0xab, 0x72, 0x20, 0xe5, 0x96, 0xcb, 0x2d, 0xbf, 0xe5, 0x4b, - 0x3a, 0xff, 0xa5, 0xa8, 0x0f, 0x87, 0xea, 0x65, 0x67, 0x38, 0x24, 0xf6, 0x6a, 0x48, 0x5c, 0xff, - 0x02, 0x3b, 0x66, 0x48, 0x30, 0xf3, 0x3d, 0x25, 0xf1, 0xf2, 0x50, 0x89, 0x84, 0x70, 0xf1, 0x68, - 0xd5, 0x72, 0xfc, 0xd3, 0xb1, 0xf0, 0xdd, 0x93, 0x03, 0x12, 0x06, 0x24, 0x6a, 0x63, 0x47, 0x49, - 0x3c, 0xba, 0x52, 0x82, 0xb5, 0x4f, 0xb1, 0x65, 0xf9, 0x6d, 0x2f, 0x52, 0x22, 0xaf, 0x5c, 0x29, - 0x72, 0x81, 0xdb, 0x8e, 0x9a, 0xad, 0xff, 0x55, 0x83, 0x5b, 0xdb, 0x6d, 0xcf, 0xa6, 0x5e, 0xeb, - 0x38, 0xb0, 0x71, 0x44, 0x4e, 0x1e, 0xa1, 0x6f, 0xc0, 0x5c, 0x62, 0x87, 0x49, 0xed, 0x8a, 0x76, - 0x5f, 0x7b, 0x50, 0x30, 0xf2, 0x09, 0xad, 0x6e, 0xa3, 0x97, 0xa0, 0xd4, 0x94, 0x52, 0xe6, 0x05, - 0x76, 0xda, 0xc4, 0x0c, 0x02, 0xb7, 0x92, 0xba, 0xaf, 0x3d, 0x98, 0x36, 0x6e, 0x29, 0xc6, 0x09, - 0xa7, 0x37, 0x02, 0x17, 0xb9, 0x50, 0x88, 0xe7, 0x0a, 0x6b, 0x2a, 0xe9, 0xfb, 0xda, 0x83, 0xb9, - 0xda, 0xce, 0x27, 0x9f, 0xdd, 0x9b, 0xfa, 0xc7, 0x67, 0xf7, 0xbe, 0xd3, 0xa2, 0xd1, 0x59, 0xfb, - 0xb4, 0x6a, 0xf9, 0xee, 0x6a, 0x8f, 0xe9, 0x17, 0xaf, 0xbd, 0x6a, 0x9d, 0x61, 0xea, 0x75, 0x6c, - 0xb7, 0xa3, 0xcb, 0x80, 0xb0, 0xea, 0x21, 0x09, 0x29, 0x76, 0xe8, 0x73, 0x7c, 0xea, 0x90, 0xba, - 0x17, 0x19, 0x73, 0x0a, 0xbe, 0xce, 0xd1, 0xf5, 0x5f, 0xa4, 0x60, 0x5e, 0xad, 0x68, 0x8b, 0xa7, - 0xc1, 0xc9, 0x23, 0xb4, 0x07, 0x33, 0x6d, 0xb1, 0x38, 0x56, 0xd1, 0xee, 0xa7, 0x1f, 0xe4, 0xd7, - 0x5e, 0xa9, 0x8e, 0x49, 0x9b, 0x6a, 0x9f, 0x3f, 0x6a, 0x19, 0x6e, 0xa9, 0x11, 0x43, 0xa0, 0x4d, - 0xc8, 0x70, 0x3b, 0xc4, 0x72, 0xe7, 0xd7, 0x1e, 0x4e, 0x02, 0xa5, 0x0c, 0xa9, 0x1e, 0x5d, 0x06, - 0xc4, 0x10, 0xd2, 0xba, 0x0b, 0x19, 0x3e, 0x42, 0x65, 0x28, 0x1e, 0xbd, 0xdf, 0xd8, 0x32, 0x8f, - 0x0f, 0x0e, 0x1b, 0x5b, 0x1b, 0xf5, 0xed, 0xfa, 0xd6, 0x66, 0x71, 0x0a, 0xdd, 0x81, 0xdb, 0x82, - 0xda, 0x30, 0xb6, 0xf6, 0xeb, 0xc7, 0xfb, 0xe6, 0xe1, 0xfa, 0x7e, 0x63, 0x6f, 0xab, 0xa8, 0xa1, - 0x7b, 0xb0, 0x22, 0x18, 0xdb, 0xc7, 0x07, 0x9b, 0xf5, 0x83, 0xb7, 0x4d, 0x63, 0xfd, 0x68, 0xcb, - 0x5c, 0x3f, 0xd8, 0x34, 0xeb, 0x07, 0x9b, 0x5b, 0xef, 0x15, 0x53, 0x68, 0x01, 0x4a, 0x3d, 0x92, - 0x27, 0x8f, 0x8f, 0xb6, 0x8a, 0x69, 0xfd, 0x2f, 0x29, 0x28, 0xec, 0xe3, 0xf0, 0x9c, 0x44, 0xb1, - 0x53, 0x56, 0x60, 0xd6, 0x15, 0x84, 0x4e, 0x88, 0x73, 0x92, 0x50, 0xb7, 0xd1, 0x13, 0x98, 0x0b, - 0x42, 0x6a, 0x11, 0x53, 0x2e, 0x5a, 0xac, 0x35, 0xbf, 0xf6, 0xfa, 0xd8, 0xb5, 0x4a, 0xf8, 0x06, - 0x17, 0x93, 0xae, 0x53, 0x9a, 0x76, 0xa6, 0x8c, 0x7c, 0xd0, 0xa1, 0xa2, 0x77, 0xa1, 0xa0, 0x14, - 0x5b, 0x21, 0xe1, 0xe0, 0x69, 0x01, 0xfe, 0x70, 0x02, 0xf0, 0x0d, 0x21, 0xd0, 0xc1, 0x9d, 0x73, - 0xbb, 0xc8, 0x5d, 0xc0, 0xae, 0x6f, 0xd3, 0xe6, 0x65, 0x25, 0x33, 0x31, 0xf0, 0xbe, 0x10, 0x18, - 0x00, 0x96, 0xe4, 0xda, 0x0c, 0x4c, 0x8b, 0xd9, 0xfa, 0x2e, 0x54, 0x46, 0xad, 0x12, 0x55, 0xe1, - 0xb6, 0x74, 0xd9, 0x33, 0x1a, 0x9d, 0x99, 0xe4, 0xc3, 0xc0, 0xf7, 0x88, 0x17, 0x09, 0xcf, 0x66, - 0x8c, 0x92, 0x60, 0xbd, 0x4b, 0xa3, 0xb3, 0x2d, 0xc5, 0xd0, 0xdf, 0x83, 0x92, 0xc4, 0xaa, 0x61, - 0x96, 0x80, 0x20, 0xc8, 0x04, 0x98, 0x86, 0x42, 0x6a, 0xd6, 0x10, 0xbf, 0xd1, 0x2a, 0x94, 0x5d, - 0xea, 0x99, 0x12, 0xdc, 0x3a, 0xc3, 0x5e, 0xab, 0xb3, 0xdd, 0x0a, 0x46, 0xc9, 0xa5, 0x9e, 0xb0, - 0x66, 0x43, 0x70, 0x1a, 0x81, 0xab, 0xb7, 0xe1, 0xf6, 0x10, 0x77, 0xa1, 0x1a, 0x64, 0x4e, 0x31, - 0x23, 0x02, 0x3b, 0xbf, 0x56, 0x9d, 0xc0, 0x2b, 0x5d, 0x96, 0x19, 0x42, 0x16, 0x2d, 0x43, 0x2e, - 0x59, 0x19, 0xd7, 0x5f, 0x32, 0x92, 0xb1, 0xfe, 0x7e, 0xac, 0xb6, 0xc7, 0x99, 0x37, 0xa1, 0x56, - 0xff, 0x9d, 0x06, 0x85, 0x43, 0xbf, 0x1d, 0x5a, 0xe4, 0x71, 0x93, 0x6f, 0x29, 0x86, 0xbe, 0x07, - 0x85, 0xce, 0xc9, 0x17, 0x67, 0xf0, 0xc8, 0x0c, 0x4d, 0x08, 0x17, 0x8f, 0xaa, 0x75, 0x49, 0x3b, - 0x4c, 0xa4, 0xeb, 0x36, 0x0f, 0x38, 0xeb, 0x1a, 0xa3, 0xd7, 0x60, 0x06, 0xdb, 0x76, 0x48, 0x18, - 0x13, 0xab, 0x9c, 0xad, 0x55, 0xfe, 0xf6, 0x87, 0x57, 0xcb, 0xea, 0x02, 0x59, 0x97, 0x9c, 0xc3, - 0x28, 0xa4, 0x5e, 0x6b, 0x67, 0xca, 0x88, 0xa7, 0xd6, 0x72, 0x90, 0x65, 0xc2, 0x48, 0xfd, 0xe3, - 0x34, 0xdc, 0x3a, 0x0a, 0xb1, 0xc7, 0x9a, 0x24, 0x8c, 0xfd, 0xd0, 0x82, 0x32, 0x23, 0x9e, 0x4d, - 0x42, 0xf3, 0xe6, 0x0c, 0x37, 0x90, 0x84, 0xec, 0xa6, 0x21, 0x17, 0xee, 0x84, 0xc4, 0xa2, 0x01, - 0x25, 0x5e, 0xd4, 0xa7, 0x2b, 0x75, 0x1d, 0x5d, 0x0b, 0x09, 0x6a, 0x8f, 0xba, 0x25, 0xc8, 0x61, - 0xc6, 0xe4, 0x31, 0x92, 0x16, 0x29, 0x39, 0x23, 0xc6, 0x75, 0x1b, 0x2d, 0x42, 0x16, 0xbb, 0x7c, - 0x9a, 0xd8, 0x89, 0x19, 0x43, 0x8d, 0x50, 0x0d, 0xb2, 0xd2, 0xee, 0xca, 0xb4, 0x30, 0xe8, 0xa5, - 0xb1, 0x49, 0xd1, 0x13, 0x78, 0x43, 0x49, 0xa2, 0x1d, 0x98, 0x4d, 0xec, 0xa9, 0x64, 0x5f, 0x18, - 0xa6, 0x23, 0xac, 0x7f, 0x94, 0x81, 0xe2, 0xe3, 0xd0, 0x26, 0xe1, 0x36, 0x75, 0x9c, 0x38, 0x5a, - 0xc7, 0x90, 0x77, 0xf1, 0x39, 0x09, 0x4d, 0x9f, 0x73, 0xc6, 0x27, 0xef, 0x10, 0xc7, 0x09, 0x3c, - 0x75, 0x71, 0x80, 0x00, 0x12, 0x14, 0xb4, 0x0d, 0xd3, 0x12, 0x30, 0xf5, 0x65, 0x00, 0x77, 0xa6, - 0x0c, 0x29, 0x8e, 0x3e, 0x80, 0x92, 0x43, 0x9f, 0xb6, 0xa9, 0x8d, 0x23, 0xea, 0x7b, 0xca, 0x48, - 0x79, 0xdc, 0xad, 0x8e, 0xf5, 0xc2, 0x5e, 0x47, 0x4a, 0x40, 0x8a, 0xd3, 0xae, 0xe8, 0xf4, 0x51, - 0xd1, 0x3d, 0xc8, 0x37, 0xa9, 0xe3, 0x98, 0x2a, 0x7c, 0x69, 0x11, 0x3e, 0xe0, 0xa4, 0x75, 0x19, - 0x42, 0x71, 0x7b, 0x70, 0xff, 0x34, 0x09, 0x11, 0x51, 0x44, 0xfc, 0xf6, 0x38, 0x27, 0xe1, 0x36, - 0x21, 0x9c, 0x19, 0x25, 0xcc, 0xac, 0x64, 0x46, 0x31, 0xf3, 0x15, 0x40, 0x91, 0x1f, 0x61, 0xc7, - 0xe4, 0x68, 0xc4, 0x36, 0x85, 0x54, 0x65, 0x46, 0x68, 0x28, 0x0a, 0xce, 0xb6, 0x60, 0xec, 0x73, - 0xfa, 0xc0, 0x6c, 0x01, 0x53, 0xc9, 0x0d, 0xcc, 0x3e, 0x12, 0xb3, 0xab, 0x70, 0x1b, 0x37, 0x9b, - 0xd4, 0xa1, 0x38, 0x22, 0x66, 0x48, 0x2e, 0x4c, 0x51, 0xba, 0x55, 0x66, 0xe5, 0x19, 0x9c, 0xb0, - 0x0c, 0x72, 0x71, 0xc8, 0x19, 0xb5, 0x02, 0xe4, 0xa3, 0x4e, 0x94, 0xf5, 0x9f, 0xa6, 0xe1, 0xf6, - 0x26, 0x71, 0xc8, 0x05, 0x09, 0x71, 0xab, 0xab, 0x7e, 0xf8, 0x2e, 0x40, 0xec, 0x21, 0x72, 0xbd, - 0x0d, 0x1b, 0xa7, 0x44, 0x07, 0x8e, 0x83, 0xfb, 0xcd, 0x26, 0x23, 0x51, 0x44, 0xbd, 0xd6, 0xb5, - 0x76, 0x68, 0x0c, 0xde, 0x81, 0x1b, 0x28, 0xe5, 0xd2, 0x83, 0xa5, 0x5c, 0x5f, 0xa8, 0x33, 0x03, - 0xa1, 0x7e, 0x08, 0x65, 0x19, 0x82, 0xa7, 0x6d, 0x3f, 0x22, 0xe6, 0xd3, 0x36, 0xf6, 0xa2, 0xb6, - 0xcb, 0x44, 0xd4, 0x33, 0x86, 0x0c, 0xcf, 0x3b, 0x9c, 0xf5, 0x8e, 0xe2, 0xa0, 0x05, 0xc8, 0x52, - 0x66, 0x9e, 0xb6, 0x2f, 0x45, 0xf0, 0x73, 0xc6, 0x34, 0x65, 0xb5, 0xf6, 0x25, 0x8f, 0x0e, 0x65, - 0x66, 0x93, 0x7a, 0xd8, 0x31, 0xb9, 0x81, 0x0e, 0x71, 0xf9, 0xe6, 0x9d, 0x11, 0x73, 0x4a, 0x94, - 0x6d, 0x73, 0xce, 0x61, 0xc2, 0xd0, 0x7f, 0x92, 0x02, 0x34, 0x98, 0xaf, 0x5f, 0x6d, 0x34, 0xee, - 0xc3, 0x1c, 0x2f, 0xd8, 0x4d, 0x7e, 0xf3, 0xc6, 0x27, 0x66, 0xc1, 0x00, 0x4e, 0x6b, 0x60, 0x1a, - 0xd6, 0xed, 0x49, 0x5c, 0xfa, 0x75, 0x00, 0xe9, 0x31, 0x46, 0x9f, 0x13, 0xe5, 0xd1, 0x59, 0x41, - 0x39, 0xa4, 0xcf, 0x49, 0x97, 0x7b, 0xa6, 0xbb, 0xdd, 0xb3, 0x0c, 0x39, 0xd6, 0x3e, 0x8d, 0xa8, - 0x75, 0xce, 0x84, 0xdf, 0x32, 0x46, 0x32, 0xd6, 0xff, 0x9d, 0x82, 0x3b, 0x1d, 0xcb, 0x7b, 0x0b, - 0x8f, 0x27, 0x37, 0x79, 0x15, 0xf6, 0x5d, 0x84, 0xcf, 0x61, 0x45, 0x56, 0x80, 0xb6, 0xd9, 0x59, - 0x74, 0xe0, 0x33, 0xca, 0x03, 0xc2, 0x2a, 0x69, 0x51, 0x4d, 0xbf, 0x35, 0xb1, 0xa6, 0x46, 0x8c, - 0xd1, 0x50, 0x10, 0xc6, 0x92, 0x82, 0x1f, 0xe0, 0x30, 0xe4, 0xc1, 0x9d, 0x58, 0xb7, 0xbc, 0x60, - 0x3a, 0x7a, 0x33, 0x42, 0xef, 0x1b, 0x13, 0xeb, 0x5d, 0xe7, 0xf2, 0x89, 0xce, 0x05, 0x05, 0xdb, - 0x43, 0x65, 0xbb, 0x99, 0x5c, 0xaa, 0x98, 0xd6, 0xff, 0x39, 0x07, 0xe5, 0xc3, 0x08, 0x47, 0xa4, - 0xd9, 0x76, 0x44, 0xc6, 0xc5, 0x6e, 0x7e, 0x0a, 0x79, 0x71, 0x4a, 0x98, 0x81, 0x83, 0xad, 0xb8, - 0x9c, 0xd9, 0x1d, 0x7f, 0xe5, 0x0c, 0xc1, 0xe9, 0x25, 0x36, 0x38, 0x96, 0x2b, 0x18, 0xb5, 0x54, - 0x45, 0xdb, 0xe1, 0xbb, 0x37, 0xa1, 0x23, 0x1f, 0x0a, 0x52, 0xa5, 0x7a, 0x7a, 0xaa, 0x13, 0x7e, - 0xe7, 0x9a, 0x4a, 0x0d, 0x89, 0x26, 0x0b, 0x5d, 0xbf, 0x8b, 0x82, 0x7e, 0xa6, 0xc1, 0x8a, 0xe5, - 0x7b, 0xb6, 0xf0, 0x08, 0x76, 0xcc, 0xae, 0x05, 0x8b, 0xad, 0x2a, 0xaf, 0xeb, 0xfd, 0x17, 0xd7, - 0xbf, 0xd1, 0x01, 0xed, 0x5f, 0xf7, 0xce, 0x94, 0xb1, 0x64, 0x8d, 0x62, 0x8f, 0xb0, 0x28, 0x0a, - 0x69, 0xab, 0x45, 0x42, 0x62, 0xab, 0x9b, 0xff, 0x06, 0x2c, 0x3a, 0x8a, 0x21, 0x87, 0x5b, 0x94, - 0xb0, 0xd1, 0x47, 0x1a, 0x2c, 0x39, 0xbe, 0xd7, 0x32, 0x23, 0x12, 0xba, 0x03, 0x1e, 0x9a, 0xf9, - 0xb2, 0x69, 0xb1, 0xe7, 0x7b, 0xad, 0x23, 0x12, 0xba, 0x43, 0xdc, 0xb3, 0xe8, 0x0c, 0xe5, 0xa1, - 0x1f, 0x40, 0x29, 0x4e, 0x8f, 0x8e, 0x01, 0x39, 0x61, 0xc0, 0xde, 0x35, 0x0d, 0x30, 0x3a, 0x88, - 0xb2, 0x42, 0xf0, 0xfb, 0xa8, 0xcb, 0xdf, 0x87, 0xca, 0xa8, 0x4c, 0x46, 0x9b, 0x71, 0x95, 0xf3, - 0xa5, 0xca, 0x26, 0x55, 0xe3, 0x2c, 0xff, 0x49, 0x83, 0xc5, 0xe1, 0x79, 0x8b, 0x9e, 0x40, 0x51, - 0x6c, 0x09, 0x62, 0xab, 0x00, 0x24, 0xa7, 0xde, 0xc3, 0x17, 0xd3, 0x55, 0xb7, 0x8d, 0x79, 0x85, - 0xa4, 0xc6, 0xe8, 0x6d, 0xc8, 0xca, 0x0e, 0x8f, 0x7a, 0xe0, 0x8f, 0xa8, 0xa7, 0x64, 0x53, 0xa8, - 0xda, 0x6d, 0x98, 0x21, 0xc4, 0x0c, 0x25, 0xbe, 0x6c, 0xc1, 0xca, 0x98, 0xb4, 0xbf, 0x21, 0x27, - 0xfd, 0x70, 0x50, 0x49, 0x57, 0x26, 0xa3, 0x0f, 0x00, 0x25, 0x7b, 0xe5, 0xfa, 0xae, 0x2a, 0x26, - 0x58, 0x8a, 0xc2, 0xb3, 0x60, 0x54, 0xe2, 0xde, 0xd0, 0x02, 0xff, 0xa8, 0xc1, 0xf2, 0xe8, 0xd4, - 0x44, 0x06, 0xcc, 0xf9, 0xce, 0x0d, 0x2c, 0x0d, 0x7c, 0x27, 0xc9, 0x80, 0xcd, 0x6b, 0x15, 0xe9, - 0xca, 0xf0, 0xa4, 0x69, 0x20, 0xef, 0x95, 0xdd, 0x4c, 0x2e, 0x5d, 0xcc, 0xe8, 0xbf, 0xd5, 0x00, - 0x89, 0x6b, 0xa7, 0xf7, 0x69, 0x3e, 0x0f, 0xa9, 0xa4, 0x09, 0x93, 0xa2, 0xe2, 0xe1, 0xc4, 0x2e, - 0xdd, 0x53, 0xdf, 0x91, 0xcf, 0x4f, 0x43, 0x8d, 0x78, 0x61, 0x71, 0x86, 0x99, 0x29, 0x9b, 0x13, - 0xa2, 0xf2, 0xc8, 0x19, 0xb3, 0x67, 0x98, 0xc9, 0x77, 0x73, 0x6f, 0x4b, 0x27, 0xd3, 0xd7, 0xd2, - 0x79, 0x19, 0x4a, 0x38, 0xf2, 0x5d, 0x6a, 0x99, 0x21, 0x61, 0xbe, 0xd3, 0xe6, 0x19, 0x23, 0x0e, - 0xf4, 0x92, 0x51, 0x94, 0x0c, 0x23, 0xa1, 0xeb, 0x7f, 0x4e, 0xc3, 0xd7, 0x92, 0x2b, 0x79, 0x58, - 0x33, 0xa1, 0xdf, 0xe2, 0xab, 0xeb, 0xa6, 0x45, 0xc8, 0xf2, 0x5a, 0x86, 0x84, 0xc2, 0xee, 0x59, - 0x43, 0x8d, 0xc6, 0x1b, 0xbd, 0x03, 0x59, 0x16, 0xe1, 0xa8, 0x2d, 0xab, 0xcd, 0xf9, 0x49, 0x02, - 0xbb, 0xa1, 0x54, 0x1e, 0x0a, 0x39, 0x43, 0xc9, 0xa3, 0x6f, 0xc3, 0x8a, 0xaa, 0x5c, 0x4d, 0xcb, - 0xf7, 0x2e, 0x48, 0xc8, 0xf8, 0xc3, 0x29, 0x69, 0x66, 0x64, 0x85, 0x23, 0x96, 0xd4, 0x94, 0x8d, - 0x64, 0x46, 0xdc, 0xae, 0x19, 0xee, 0xbe, 0x99, 0xe1, 0xee, 0x43, 0x2f, 0x41, 0x29, 0x2e, 0xdd, - 0x78, 0xdd, 0x64, 0xf2, 0x5f, 0xe2, 0x64, 0x2e, 0x18, 0xb7, 0x62, 0x46, 0x83, 0x84, 0x47, 0xd4, - 0x3a, 0xe7, 0x2f, 0x1c, 0x16, 0x91, 0xc0, 0x3c, 0xc5, 0xac, 0xab, 0xb8, 0x96, 0x4f, 0x96, 0x22, - 0xe7, 0xd4, 0x30, 0xeb, 0x94, 0xd6, 0xdf, 0x84, 0x79, 0x59, 0xad, 0xd2, 0xe8, 0xd2, 0x8c, 0x28, - 0x09, 0x2b, 0x20, 0x60, 0x0b, 0x09, 0xf5, 0x88, 0x92, 0xf0, 0xad, 0x54, 0x45, 0xd3, 0x7f, 0x99, - 0x19, 0x1b, 0xc3, 0xb5, 0xff, 0xc7, 0xf0, 0xbf, 0x3a, 0x86, 0xe8, 0x04, 0xf2, 0xca, 0xa9, 0xa2, - 0xdd, 0x9c, 0x17, 0xce, 0x9b, 0xa0, 0xaa, 0xef, 0x8b, 0xb9, 0xe8, 0x39, 0x83, 0x9b, 0xfc, 0xd6, - 0x7f, 0x93, 0x82, 0xe5, 0xbd, 0x6e, 0x4d, 0xc7, 0x01, 0x23, 0x61, 0x34, 0x6a, 0x67, 0x23, 0xc8, - 0x78, 0xd8, 0x25, 0xea, 0x24, 0x12, 0xbf, 0xf9, 0x7a, 0xa9, 0x47, 0x23, 0x8a, 0x1d, 0x7e, 0x16, - 0xb5, 0xa8, 0x27, 0x1a, 0x92, 0xf2, 0x25, 0x54, 0x54, 0x9c, 0x7d, 0xc1, 0x68, 0x04, 0x2e, 0x7a, - 0x13, 0x2a, 0x2e, 0xa6, 0x5e, 0x44, 0x3c, 0xec, 0x59, 0xc4, 0x6c, 0x86, 0xd8, 0x12, 0x5d, 0x0b, - 0x2e, 0x23, 0x93, 0x65, 0xb1, 0x8b, 0xbf, 0xad, 0xd8, 0x52, 0x72, 0x51, 0xb8, 0x34, 0xae, 0xfc, - 0x4d, 0xcf, 0x97, 0x17, 0x9d, 0x7c, 0x7c, 0xf2, 0x92, 0xd9, 0x28, 0xf3, 0x19, 0x71, 0x15, 0x7f, - 0xa0, 0xf8, 0xbb, 0x99, 0x5c, 0xb6, 0x38, 0xb3, 0x9b, 0xc9, 0xcd, 0x14, 0x73, 0xc6, 0x1d, 0x3f, - 0x20, 0x9e, 0xc9, 0x15, 0x84, 0x84, 0x45, 0xa6, 0xe3, 0x3f, 0x23, 0xa1, 0x69, 0xe1, 0xa0, 0x9f, - 0xd1, 0x0e, 0x02, 0xc9, 0xd0, 0x7f, 0x9d, 0x82, 0x05, 0xf9, 0xc8, 0x8a, 0x33, 0x31, 0xf6, 0x4e, - 0xff, 0x1e, 0xd1, 0x06, 0xf6, 0x48, 0x27, 0xdd, 0x53, 0x5f, 0x6d, 0xba, 0xa7, 0xaf, 0x4a, 0xf7, - 0xa1, 0x19, 0x9c, 0x79, 0x91, 0x0c, 0x9e, 0x1e, 0x9e, 0xc1, 0xfa, 0xef, 0x35, 0x58, 0x94, 0xfe, - 0x49, 0x92, 0x6d, 0xcc, 0x55, 0xa6, 0x8e, 0x8c, 0xd4, 0xe8, 0x23, 0x23, 0x3d, 0xc9, 0x5d, 0x95, - 0x19, 0xb1, 0x51, 0x07, 0xb7, 0xd3, 0xf4, 0x90, 0xed, 0xa4, 0x33, 0x58, 0x38, 0x0a, 0xb1, 0x4d, - 0xbd, 0x96, 0x41, 0x9e, 0xe1, 0xd0, 0x66, 0x9d, 0xf7, 0xf3, 0xad, 0x48, 0x32, 0xcc, 0x50, 0x72, - 0xd4, 0x57, 0xa2, 0x47, 0x63, 0x8b, 0x68, 0xd5, 0x06, 0xee, 0xc1, 0x34, 0xe6, 0xa3, 0x1e, 0x15, - 0xfa, 0xaf, 0x34, 0x28, 0x0f, 0x9b, 0x88, 0xca, 0x30, 0xed, 0x3f, 0xf3, 0x48, 0xdc, 0xe9, 0x97, - 0x03, 0x74, 0x0e, 0x73, 0x36, 0xf1, 0x7c, 0x37, 0x6e, 0xc6, 0xa4, 0x6e, 0xf8, 0x4b, 0x59, 0x5e, - 0xa0, 0xcb, 0xbe, 0x8e, 0xfe, 0x23, 0x0d, 0x96, 0x1e, 0x07, 0xc4, 0xab, 0xab, 0xfc, 0xef, 0xed, - 0x2a, 0x58, 0xb0, 0xd0, 0xbf, 0x3b, 0xba, 0xbf, 0xa0, 0x8d, 0xef, 0x32, 0x0e, 0xc2, 0x1a, 0xb7, - 0xfd, 0x01, 0x1a, 0x13, 0xd7, 0xd4, 0xc7, 0x1a, 0xa0, 0xc1, 0xf9, 0x93, 0x7c, 0x84, 0x74, 0xa1, - 0xd0, 0x63, 0xe2, 0x8d, 0xbb, 0x6b, 0xae, 0xdb, 0x66, 0x61, 0xec, 0xa7, 0xe3, 0xce, 0xce, 0xb5, - 0xff, 0x8d, 0xb3, 0x13, 0xbd, 0x0e, 0xa3, 0x4e, 0x4c, 0xd5, 0x97, 0x2a, 0x77, 0xfb, 0x65, 0x8f, - 0x33, 0x37, 0x70, 0x30, 0x28, 0x96, 0x9c, 0xa7, 0xaa, 0xbb, 0x5b, 0xee, 0x4d, 0x81, 0x40, 0x88, - 0xe9, 0x3f, 0xd6, 0xa0, 0x62, 0x90, 0x16, 0x65, 0x11, 0x09, 0xd7, 0xe3, 0x0e, 0x6d, 0x9c, 0x85, - 0x6b, 0x30, 0x13, 0x92, 0x26, 0x09, 0x89, 0x6c, 0xb8, 0x8c, 0xf9, 0x10, 0x63, 0xc4, 0x13, 0xd1, - 0x1b, 0x30, 0x9b, 0x74, 0x7a, 0xaf, 0xfa, 0x7c, 0x63, 0x74, 0xa6, 0xf2, 0x43, 0x0d, 0xc9, 0x70, - 0x9e, 0xe0, 0xb6, 0x13, 0x75, 0x99, 0x10, 0x7f, 0x0b, 0xba, 0xd2, 0x04, 0x35, 0x71, 0x82, 0x4a, - 0x6a, 0x2b, 0xb9, 0x25, 0xd2, 0xe2, 0x96, 0x78, 0xf5, 0xea, 0x5b, 0x42, 0x58, 0xd5, 0x7b, 0x45, - 0xd4, 0x8c, 0x4f, 0x3e, 0xbf, 0xab, 0x7d, 0xfa, 0xf9, 0x5d, 0xed, 0x5f, 0x9f, 0xdf, 0xd5, 0x7e, - 0xfe, 0xc5, 0xdd, 0xa9, 0x4f, 0xbf, 0xb8, 0x3b, 0xf5, 0xf7, 0x2f, 0xee, 0x4e, 0x3d, 0x79, 0x73, - 0xf2, 0xec, 0xef, 0xfd, 0xff, 0x8a, 0xd3, 0xac, 0x60, 0x7c, 0xeb, 0x3f, 0x01, 0x00, 0x00, 0xff, - 0xff, 0x35, 0x4a, 0x0d, 0x23, 0x85, 0x21, 0x00, 0x00, + // 2458 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xec, 0x5a, 0xcd, 0x6f, 0x23, 0x49, + 0x15, 0x4f, 0xdb, 0x8e, 0xe3, 0x3c, 0xc7, 0x19, 0xbb, 0xe2, 0x64, 0x9c, 0x04, 0x32, 0x43, 0x4b, + 0x48, 0xa3, 0xd9, 0x19, 0x67, 0x12, 0x76, 0x57, 0xab, 0x3d, 0x20, 0xe2, 0x7c, 0x6c, 0x1c, 0x25, + 0x19, 0x6f, 0xe7, 0x63, 0x77, 0x07, 0xb4, 0x4d, 0xa5, 0xbb, 0xec, 0x94, 0xd2, 0x5f, 0xd3, 0xdd, + 0xce, 0x4c, 0x06, 0x71, 0x43, 0x2c, 0x48, 0x48, 0x20, 0x21, 0x0e, 0x1c, 0x90, 0xb8, 0x70, 0x59, + 0x89, 0x03, 0x12, 0x70, 0xe3, 0x80, 0xb8, 0xec, 0x8d, 0x11, 0x27, 0x04, 0xd2, 0x0a, 0xcd, 0x1c, + 0xf8, 0x37, 0x50, 0x7d, 0x74, 0xfb, 0xdb, 0xf1, 0x4c, 0xb2, 0xd2, 0x0a, 0xed, 0x29, 0xae, 0xf7, + 0xea, 0xfd, 0xde, 0xab, 0xf7, 0x5e, 0x55, 0xbd, 0x7a, 0x1d, 0xb8, 0x63, 0x5e, 0x98, 0x4f, 0x3d, + 0xdf, 0x0d, 0x5d, 0xc3, 0xb5, 0x96, 0xa9, 0x63, 0x92, 0xa7, 0xc4, 0x5f, 0x26, 0xe7, 0xc4, 0x09, + 0x03, 0xf9, 0xa7, 0xcc, 0xd9, 0x68, 0xb1, 0x7d, 0x66, 0x59, 0xce, 0x2c, 0x8b, 0x29, 0x0b, 0xf3, + 0x86, 0x1b, 0xd8, 0x6e, 0xa0, 0x73, 0xfe, 0xb2, 0x18, 0x08, 0xb9, 0x85, 0x62, 0xc3, 0x6d, 0xb8, + 0x82, 0xce, 0x7e, 0x49, 0xea, 0x83, 0xbe, 0x7a, 0x83, 0x53, 0xec, 0x13, 0x73, 0xd9, 0x27, 0xb6, + 0x7b, 0x8e, 0x2d, 0xdd, 0x27, 0x38, 0x70, 0x1d, 0x29, 0xf1, 0x46, 0x5f, 0x89, 0x98, 0x70, 0xbe, + 0xb2, 0x6c, 0x58, 0xee, 0xc9, 0x50, 0xf8, 0xf6, 0xc9, 0x1e, 0xf1, 0x3d, 0x12, 0x36, 0xb1, 0x25, + 0x25, 0x56, 0x2e, 0x95, 0x08, 0x9a, 0x27, 0xd8, 0x30, 0xdc, 0xa6, 0x13, 0x4a, 0x91, 0x7b, 0x97, + 0x8a, 0x9c, 0xe3, 0xa6, 0x25, 0x67, 0xab, 0x7f, 0x57, 0xe0, 0xc6, 0x56, 0xd3, 0x31, 0xa9, 0xd3, + 0x38, 0xf2, 0x4c, 0x1c, 0x92, 0xe3, 0x15, 0xf4, 0x0d, 0x98, 0x8a, 0xed, 0xd0, 0xa9, 0x59, 0x52, + 0x6e, 0x2b, 0x77, 0x72, 0x5a, 0x36, 0xa6, 0x55, 0x4d, 0x74, 0x17, 0x0a, 0x75, 0x21, 0xa5, 0x9f, + 0x63, 0xab, 0x49, 0x74, 0xcf, 0xb3, 0x4b, 0x89, 0xdb, 0xca, 0x9d, 0x71, 0xed, 0x86, 0x64, 0x1c, + 0x33, 0x7a, 0xcd, 0xb3, 0x91, 0x0d, 0xb9, 0x68, 0x2e, 0xb7, 0xa6, 0x94, 0xbc, 0xad, 0xdc, 0x99, + 0xaa, 0x6c, 0x7f, 0xf6, 0xf9, 0xad, 0xb1, 0x7f, 0x7d, 0x7e, 0xeb, 0x3b, 0x0d, 0x1a, 0x9e, 0x36, + 0x4f, 0xca, 0x86, 0x6b, 0x2f, 0x77, 0x98, 0x7e, 0xfe, 0xe6, 0x7d, 0xe3, 0x14, 0x53, 0xa7, 0x65, + 0xbb, 0x19, 0x5e, 0x78, 0x24, 0x28, 0x1f, 0x10, 0x9f, 0x62, 0x8b, 0x3e, 0xc3, 0x27, 0x16, 0xa9, + 0x3a, 0xa1, 0x36, 0x25, 0xe1, 0xab, 0x0c, 0x5d, 0xfd, 0x65, 0x02, 0xa6, 0xe5, 0x8a, 0x36, 0x59, + 0x1a, 0x1c, 0xaf, 0xa0, 0x5d, 0x98, 0x68, 0xf2, 0xc5, 0x05, 0x25, 0xe5, 0x76, 0xf2, 0x4e, 0x76, + 0xf5, 0x5e, 0x79, 0x48, 0xda, 0x94, 0xbb, 0xfc, 0x51, 0x49, 0x31, 0x4b, 0xb5, 0x08, 0x02, 0x6d, + 0x40, 0x8a, 0xd9, 0xc1, 0x97, 0x3b, 0xbd, 0xfa, 0x60, 0x14, 0x28, 0x69, 0x48, 0xf9, 0xf0, 0xc2, + 0x23, 0x1a, 0x97, 0x56, 0x6d, 0x48, 0xb1, 0x11, 0x2a, 0x42, 0xfe, 0xf0, 0xa3, 0xda, 0xa6, 0x7e, + 0xb4, 0x7f, 0x50, 0xdb, 0x5c, 0xaf, 0x6e, 0x55, 0x37, 0x37, 0xf2, 0x63, 0xe8, 0x26, 0xcc, 0x70, + 0x6a, 0x4d, 0xdb, 0xdc, 0xab, 0x1e, 0xed, 0xe9, 0x07, 0x6b, 0x7b, 0xb5, 0xdd, 0xcd, 0xbc, 0x82, + 0x6e, 0xc1, 0x22, 0x67, 0x6c, 0x1d, 0xed, 0x6f, 0x54, 0xf7, 0xdf, 0xd3, 0xb5, 0xb5, 0xc3, 0x4d, + 0x7d, 0x6d, 0x7f, 0x43, 0xaf, 0xee, 0x6f, 0x6c, 0x7e, 0x98, 0x4f, 0xa0, 0x59, 0x28, 0x74, 0x48, + 0x1e, 0x3f, 0x3c, 0xdc, 0xcc, 0x27, 0xd5, 0xbf, 0x25, 0x20, 0xb7, 0x87, 0xfd, 0x33, 0x12, 0x46, + 0x4e, 0x59, 0x84, 0x49, 0x9b, 0x13, 0x5a, 0x21, 0xce, 0x08, 0x42, 0xd5, 0x44, 0x8f, 0x60, 0xca, + 0xf3, 0xa9, 0x41, 0x74, 0xb1, 0x68, 0xbe, 0xd6, 0xec, 0xea, 0x5b, 0x43, 0xd7, 0x2a, 0xe0, 0x6b, + 0x4c, 0x4c, 0xb8, 0x4e, 0x6a, 0xda, 0x1e, 0xd3, 0xb2, 0x5e, 0x8b, 0x8a, 0x3e, 0x80, 0x9c, 0x54, + 0x6c, 0xf8, 0x84, 0x81, 0x27, 0x39, 0xf8, 0x83, 0x11, 0xc0, 0xd7, 0xb9, 0x40, 0x0b, 0x77, 0xca, + 0x6e, 0x23, 0xb7, 0x01, 0xdb, 0xae, 0x49, 0xeb, 0x17, 0xa5, 0xd4, 0xc8, 0xc0, 0x7b, 0x5c, 0xa0, + 0x07, 0x58, 0x90, 0x2b, 0x13, 0x30, 0xce, 0x67, 0xab, 0x3b, 0x50, 0x1a, 0xb4, 0x4a, 0x54, 0x86, + 0x19, 0xe1, 0xb2, 0x27, 0x34, 0x3c, 0xd5, 0xc9, 0x53, 0xcf, 0x75, 0x88, 0x13, 0x72, 0xcf, 0xa6, + 0xb4, 0x02, 0x67, 0x7d, 0x40, 0xc3, 0xd3, 0x4d, 0xc9, 0x50, 0x3f, 0x84, 0x82, 0xc0, 0xaa, 0xe0, + 0x20, 0x06, 0x41, 0x90, 0xf2, 0x30, 0xf5, 0xb9, 0xd4, 0xa4, 0xc6, 0x7f, 0xa3, 0x65, 0x28, 0xda, + 0xd4, 0xd1, 0x05, 0xb8, 0x71, 0x8a, 0x9d, 0x46, 0x6b, 0xbb, 0xe5, 0xb4, 0x82, 0x4d, 0x1d, 0x6e, + 0xcd, 0x3a, 0xe7, 0xd4, 0x3c, 0x5b, 0x6d, 0xc2, 0x4c, 0x1f, 0x77, 0xa1, 0x0a, 0xa4, 0x4e, 0x70, + 0x40, 0x38, 0x76, 0x76, 0xb5, 0x3c, 0x82, 0x57, 0xda, 0x2c, 0xd3, 0xb8, 0x2c, 0x5a, 0x80, 0x4c, + 0xbc, 0x32, 0xa6, 0xbf, 0xa0, 0xc5, 0x63, 0xf5, 0xa3, 0x48, 0x6d, 0x87, 0x33, 0xaf, 0x43, 0xad, + 0xfa, 0x7b, 0x05, 0x72, 0x07, 0x6e, 0xd3, 0x37, 0xc8, 0xc3, 0x3a, 0xdb, 0x52, 0x01, 0xfa, 0x1e, + 0xe4, 0x5a, 0x27, 0x5f, 0x94, 0xc1, 0x03, 0x33, 0x34, 0x26, 0x9c, 0xaf, 0x94, 0xab, 0x82, 0x76, + 0x10, 0x4b, 0x57, 0x4d, 0x16, 0xf0, 0xa0, 0x6d, 0x8c, 0xde, 0x84, 0x09, 0x6c, 0x9a, 0x3e, 0x09, + 0x02, 0xbe, 0xca, 0xc9, 0x4a, 0xe9, 0x1f, 0x7f, 0xbc, 0x5f, 0x94, 0x17, 0xc8, 0x9a, 0xe0, 0x1c, + 0x84, 0x3e, 0x75, 0x1a, 0xdb, 0x63, 0x5a, 0x34, 0xb5, 0x92, 0x81, 0x74, 0xc0, 0x8d, 0x54, 0x3f, + 0x4d, 0xc2, 0x8d, 0x43, 0x1f, 0x3b, 0x41, 0x9d, 0xf8, 0x91, 0x1f, 0x1a, 0x50, 0x0c, 0x88, 0x63, + 0x12, 0x5f, 0xbf, 0x3e, 0xc3, 0x35, 0x24, 0x20, 0xdb, 0x69, 0xc8, 0x86, 0x9b, 0x3e, 0x31, 0xa8, + 0x47, 0x89, 0x13, 0x76, 0xe9, 0x4a, 0x5c, 0x45, 0xd7, 0x6c, 0x8c, 0xda, 0xa1, 0x6e, 0x1e, 0x32, + 0x38, 0x08, 0xc4, 0x31, 0x92, 0xe4, 0x29, 0x39, 0xc1, 0xc7, 0x55, 0x13, 0xcd, 0x41, 0x1a, 0xdb, + 0x6c, 0x1a, 0xdf, 0x89, 0x29, 0x4d, 0x8e, 0x50, 0x05, 0xd2, 0xc2, 0xee, 0xd2, 0x38, 0x37, 0xe8, + 0xee, 0xd0, 0xa4, 0xe8, 0x08, 0xbc, 0x26, 0x25, 0xd1, 0x36, 0x4c, 0xc6, 0xf6, 0x94, 0xd2, 0xaf, + 0x0c, 0xd3, 0x12, 0x56, 0x3f, 0x49, 0x41, 0xfe, 0xa1, 0x6f, 0x12, 0x7f, 0x8b, 0x5a, 0x56, 0x14, + 0xad, 0x23, 0xc8, 0xda, 0xf8, 0x8c, 0xf8, 0xba, 0xcb, 0x38, 0xc3, 0x93, 0xb7, 0x8f, 0xe3, 0x38, + 0x9e, 0xbc, 0x38, 0x80, 0x03, 0x71, 0x0a, 0xda, 0x82, 0x71, 0x01, 0x98, 0x78, 0x1d, 0xc0, 0xed, + 0x31, 0x4d, 0x88, 0xa3, 0x8f, 0xa1, 0x60, 0xd1, 0xc7, 0x4d, 0x6a, 0xe2, 0x90, 0xba, 0x8e, 0x34, + 0x52, 0x1c, 0x77, 0xcb, 0x43, 0xbd, 0xb0, 0xdb, 0x92, 0xe2, 0x90, 0xfc, 0xb4, 0xcb, 0x5b, 0x5d, + 0x54, 0x74, 0x0b, 0xb2, 0x75, 0x6a, 0x59, 0xba, 0x0c, 0x5f, 0x92, 0x87, 0x0f, 0x18, 0x69, 0x4d, + 0x84, 0x90, 0xdf, 0x1e, 0xcc, 0x3f, 0x75, 0x42, 0x78, 0x14, 0x11, 0xbb, 0x3d, 0xce, 0x88, 0xbf, + 0x45, 0x08, 0x63, 0x86, 0x31, 0x33, 0x2d, 0x98, 0x61, 0xc4, 0xbc, 0x07, 0x28, 0x74, 0x43, 0x6c, + 0xe9, 0x0c, 0x8d, 0x98, 0x3a, 0x97, 0x2a, 0x4d, 0x70, 0x0d, 0x79, 0xce, 0xd9, 0xe2, 0x8c, 0x3d, + 0x46, 0xef, 0x99, 0xcd, 0x61, 0x4a, 0x99, 0x9e, 0xd9, 0x87, 0x7c, 0x76, 0x19, 0x66, 0x70, 0xbd, + 0x4e, 0x2d, 0x8a, 0x43, 0xa2, 0xfb, 0xe4, 0x5c, 0xe7, 0xa5, 0x5b, 0x69, 0x52, 0x9c, 0xc1, 0x31, + 0x4b, 0x23, 0xe7, 0x07, 0x8c, 0x51, 0xc9, 0x41, 0x36, 0x6c, 0x45, 0x59, 0xfd, 0x59, 0x12, 0x66, + 0x36, 0x88, 0x45, 0xce, 0x89, 0x8f, 0x1b, 0x6d, 0xf5, 0xc3, 0x77, 0x01, 0x22, 0x0f, 0x91, 0xab, + 0x6d, 0xd8, 0x28, 0x25, 0x5a, 0x70, 0x0c, 0xdc, 0xad, 0xd7, 0x03, 0x12, 0x86, 0xd4, 0x69, 0x5c, + 0x69, 0x87, 0x46, 0xe0, 0x2d, 0xb8, 0x9e, 0x52, 0x2e, 0xd9, 0x5b, 0xca, 0x75, 0x85, 0x3a, 0xd5, + 0x13, 0xea, 0x07, 0x50, 0x14, 0x21, 0x78, 0xdc, 0x74, 0x43, 0xa2, 0x3f, 0x6e, 0x62, 0x27, 0x6c, + 0xda, 0x01, 0x8f, 0x7a, 0x4a, 0x13, 0xe1, 0x79, 0x9f, 0xb1, 0xde, 0x97, 0x1c, 0x34, 0x0b, 0x69, + 0x1a, 0xe8, 0x27, 0xcd, 0x0b, 0x1e, 0xfc, 0x8c, 0x36, 0x4e, 0x83, 0x4a, 0xf3, 0x82, 0x45, 0x87, + 0x06, 0x7a, 0x9d, 0x3a, 0xd8, 0xd2, 0x99, 0x81, 0x16, 0xb1, 0xd9, 0xe6, 0x9d, 0xe0, 0x73, 0x0a, + 0x34, 0xd8, 0x62, 0x9c, 0x83, 0x98, 0xa1, 0xfe, 0x24, 0x01, 0xa8, 0x37, 0x5f, 0xbf, 0xd8, 0x68, + 0xdc, 0x86, 0x29, 0x56, 0xb0, 0xeb, 0xec, 0xe6, 0x8d, 0x4e, 0xcc, 0x9c, 0x06, 0x8c, 0x56, 0xc3, + 0xd4, 0xaf, 0x9a, 0xa3, 0xb8, 0xf4, 0xeb, 0x00, 0xc2, 0x63, 0x01, 0x7d, 0x46, 0xa4, 0x47, 0x27, + 0x39, 0xe5, 0x80, 0x3e, 0x23, 0x6d, 0xee, 0x19, 0x6f, 0x77, 0xcf, 0x02, 0x64, 0x82, 0xe6, 0x49, + 0x48, 0x8d, 0xb3, 0x80, 0xfb, 0x2d, 0xa5, 0xc5, 0x63, 0xf5, 0xbf, 0x09, 0xb8, 0xd9, 0xb2, 0xbc, + 0xb3, 0xf0, 0x78, 0x74, 0x9d, 0x57, 0x61, 0xd7, 0x45, 0xf8, 0x0c, 0x16, 0x45, 0x05, 0x68, 0xea, + 0xad, 0x45, 0x7b, 0x6e, 0x40, 0x59, 0x40, 0x82, 0x52, 0x92, 0x57, 0xd3, 0xef, 0x8e, 0xac, 0xa9, + 0x16, 0x61, 0xd4, 0x24, 0x84, 0x36, 0x2f, 0xe1, 0x7b, 0x38, 0x01, 0x72, 0xe0, 0x66, 0xa4, 0x5b, + 0x5c, 0x30, 0x2d, 0xbd, 0x29, 0xae, 0xf7, 0xed, 0x91, 0xf5, 0xae, 0x31, 0xf9, 0x58, 0xe7, 0xac, + 0x84, 0xed, 0xa0, 0x06, 0x3b, 0xa9, 0x4c, 0x22, 0x9f, 0x54, 0xff, 0x3d, 0x05, 0xc5, 0x83, 0x10, + 0x87, 0xa4, 0xde, 0xb4, 0x78, 0xc6, 0x45, 0x6e, 0x7e, 0x0c, 0x59, 0x7e, 0x4a, 0xe8, 0x9e, 0x85, + 0x8d, 0xa8, 0x9c, 0xd9, 0x19, 0x7e, 0xe5, 0xf4, 0xc1, 0xe9, 0x24, 0xd6, 0x18, 0x96, 0xcd, 0x19, + 0x95, 0x44, 0x49, 0xd9, 0x66, 0xbb, 0x37, 0xa6, 0x23, 0x17, 0x72, 0x42, 0xa5, 0x7c, 0x7a, 0xca, + 0x13, 0x7e, 0xfb, 0x8a, 0x4a, 0x35, 0x81, 0x26, 0x0a, 0x5d, 0xb7, 0x8d, 0x82, 0x7e, 0xae, 0xc0, + 0xa2, 0xe1, 0x3a, 0x26, 0xf7, 0x08, 0xb6, 0xf4, 0xb6, 0x05, 0xf3, 0xad, 0x2a, 0xae, 0xeb, 0xbd, + 0x57, 0xd7, 0xbf, 0xde, 0x02, 0xed, 0x5e, 0xf7, 0xf6, 0x98, 0x36, 0x6f, 0x0c, 0x62, 0x0f, 0xb0, + 0x28, 0xf4, 0x69, 0xa3, 0x41, 0x7c, 0x62, 0xca, 0x9b, 0xff, 0x1a, 0x2c, 0x3a, 0x8c, 0x20, 0xfb, + 0x5b, 0x14, 0xb3, 0xd1, 0x27, 0x0a, 0xcc, 0x5b, 0xae, 0xd3, 0xd0, 0x43, 0xe2, 0xdb, 0x3d, 0x1e, + 0x9a, 0x78, 0xdd, 0xb4, 0xd8, 0x75, 0x9d, 0xc6, 0x21, 0xf1, 0xed, 0x3e, 0xee, 0x99, 0xb3, 0xfa, + 0xf2, 0xd0, 0x0f, 0xa0, 0x10, 0xa5, 0x47, 0xcb, 0x80, 0x0c, 0x37, 0x60, 0xf7, 0x8a, 0x06, 0x68, + 0x2d, 0x44, 0x51, 0x21, 0xb8, 0x5d, 0xd4, 0x85, 0xef, 0x43, 0x69, 0x50, 0x26, 0xa3, 0x8d, 0xa8, + 0xca, 0x79, 0xad, 0xb2, 0x49, 0xd6, 0x38, 0x0b, 0x7f, 0x51, 0x60, 0xae, 0x7f, 0xde, 0xa2, 0x47, + 0x90, 0xe7, 0x5b, 0x82, 0x98, 0x32, 0x00, 0xf1, 0xa9, 0xf7, 0xe0, 0xd5, 0x74, 0x55, 0x4d, 0x6d, + 0x5a, 0x22, 0xc9, 0x31, 0x7a, 0x0f, 0xd2, 0xa2, 0xc3, 0x23, 0x1f, 0xf8, 0x03, 0xea, 0x29, 0xd1, + 0x14, 0x2a, 0xb7, 0x1b, 0xa6, 0x71, 0x31, 0x4d, 0x8a, 0x2f, 0x18, 0xb0, 0x38, 0x24, 0xed, 0xaf, + 0xc9, 0x49, 0x3f, 0xec, 0x55, 0xd2, 0x96, 0xc9, 0xe8, 0x63, 0x40, 0xf1, 0x5e, 0xb9, 0xba, 0xab, + 0xf2, 0x31, 0x96, 0xa4, 0xb0, 0x2c, 0x18, 0x94, 0xb8, 0xd7, 0xb4, 0xc0, 0x3f, 0x2b, 0xb0, 0x30, + 0x38, 0x35, 0x91, 0x06, 0x53, 0xae, 0x75, 0x0d, 0x4b, 0x03, 0xd7, 0x8a, 0x33, 0x60, 0xe3, 0x4a, + 0x45, 0xba, 0x34, 0x3c, 0x6e, 0x1a, 0x88, 0x7b, 0x65, 0x27, 0x95, 0x49, 0xe6, 0x53, 0xea, 0xef, + 0x14, 0x40, 0xfc, 0xda, 0xe9, 0x7c, 0x9a, 0x4f, 0x43, 0x22, 0x6e, 0xc2, 0x24, 0x28, 0x7f, 0x38, + 0x05, 0x17, 0xf6, 0x89, 0x6b, 0x89, 0xe7, 0xa7, 0x26, 0x47, 0xac, 0xb0, 0x38, 0xc5, 0x81, 0x2e, + 0x9a, 0x13, 0xbc, 0xf2, 0xc8, 0x68, 0x93, 0xa7, 0x38, 0x10, 0xef, 0xe6, 0xce, 0x96, 0x4e, 0xaa, + 0xab, 0xa5, 0xf3, 0x06, 0x14, 0x70, 0xe8, 0xda, 0xd4, 0xd0, 0x7d, 0x12, 0xb8, 0x56, 0x93, 0x65, + 0x0c, 0x3f, 0xd0, 0x0b, 0x5a, 0x5e, 0x30, 0xb4, 0x98, 0xae, 0xfe, 0x35, 0x09, 0x5f, 0x8b, 0xaf, + 0xe4, 0x7e, 0xcd, 0x84, 0x6e, 0x8b, 0x2f, 0xaf, 0x9b, 0xe6, 0x20, 0xcd, 0x6a, 0x19, 0xe2, 0x73, + 0xbb, 0x27, 0x35, 0x39, 0x1a, 0x6e, 0xf4, 0x36, 0xa4, 0x83, 0x10, 0x87, 0x4d, 0x51, 0x6d, 0x4e, + 0x8f, 0x12, 0xd8, 0x75, 0xa9, 0xf2, 0x80, 0xcb, 0x69, 0x52, 0x1e, 0x7d, 0x1b, 0x16, 0x65, 0xe5, + 0xaa, 0x1b, 0xae, 0x73, 0x4e, 0xfc, 0x80, 0x3d, 0x9c, 0xe2, 0x66, 0x46, 0x9a, 0x3b, 0x62, 0x5e, + 0x4e, 0x59, 0x8f, 0x67, 0x44, 0xed, 0x9a, 0xfe, 0xee, 0x9b, 0xe8, 0xef, 0x3e, 0x74, 0x17, 0x0a, + 0x51, 0xe9, 0xc6, 0xea, 0x26, 0x9d, 0xfd, 0xe2, 0x27, 0x73, 0x4e, 0xbb, 0x11, 0x31, 0x6a, 0xc4, + 0x3f, 0xa4, 0xc6, 0x19, 0x7b, 0xe1, 0x04, 0x21, 0xf1, 0xf4, 0x13, 0x1c, 0xb4, 0x15, 0xd7, 0xe2, + 0xc9, 0x92, 0x67, 0x9c, 0x0a, 0x0e, 0x5a, 0xa5, 0xf5, 0x37, 0x61, 0x5a, 0x54, 0xab, 0x34, 0xbc, + 0xd0, 0x43, 0x4a, 0xfc, 0x12, 0x70, 0xd8, 0x5c, 0x4c, 0x3d, 0xa4, 0xc4, 0x7f, 0x37, 0x51, 0x52, + 0xd4, 0x5f, 0xa5, 0x86, 0xc6, 0x70, 0xf5, 0xab, 0x18, 0x7e, 0xa9, 0x63, 0x88, 0x8e, 0x21, 0x2b, + 0x9d, 0xca, 0xdb, 0xcd, 0x59, 0xee, 0xbc, 0x11, 0xaa, 0xfa, 0xae, 0x98, 0xf3, 0x9e, 0x33, 0xd8, + 0xf1, 0x6f, 0xf5, 0xb7, 0x09, 0x58, 0xd8, 0x6d, 0xd7, 0x74, 0xe4, 0x05, 0xc4, 0x0f, 0x07, 0xed, + 0x6c, 0x04, 0x29, 0x07, 0xdb, 0x44, 0x9e, 0x44, 0xfc, 0x37, 0x5b, 0x2f, 0x75, 0x68, 0x48, 0xb1, + 0xc5, 0xce, 0xa2, 0x06, 0x75, 0x78, 0x43, 0x52, 0xbc, 0x84, 0xf2, 0x92, 0xb3, 0xc7, 0x19, 0x35, + 0xcf, 0x46, 0xef, 0x40, 0xc9, 0xc6, 0xd4, 0x09, 0x89, 0x83, 0x1d, 0x83, 0xe8, 0x75, 0x1f, 0x1b, + 0xbc, 0x6b, 0xc1, 0x64, 0x44, 0xb2, 0xcc, 0xb5, 0xf1, 0xb7, 0x24, 0x5b, 0x48, 0xce, 0x71, 0x97, + 0x46, 0x95, 0xbf, 0xee, 0xb8, 0xe2, 0xa2, 0x13, 0x8f, 0x4f, 0x56, 0x32, 0x6b, 0x45, 0x36, 0x23, + 0xaa, 0xe2, 0xf7, 0x25, 0x7f, 0x27, 0x95, 0x49, 0xe7, 0x27, 0x76, 0x52, 0x99, 0x89, 0x7c, 0x46, + 0xbb, 0xe9, 0x7a, 0xc4, 0xd1, 0x99, 0x02, 0x9f, 0x04, 0xa1, 0x6e, 0xb9, 0x4f, 0x88, 0xaf, 0x1b, + 0xd8, 0xeb, 0x66, 0x34, 0x3d, 0x4f, 0x30, 0xd4, 0xdf, 0x24, 0x60, 0x56, 0x3c, 0xb2, 0xa2, 0x4c, + 0x8c, 0xbc, 0xd3, 0xbd, 0x47, 0x94, 0x9e, 0x3d, 0xd2, 0x4a, 0xf7, 0xc4, 0x17, 0x9b, 0xee, 0xc9, + 0xcb, 0xd2, 0xbd, 0x6f, 0x06, 0xa7, 0x5e, 0x25, 0x83, 0xc7, 0xfb, 0x67, 0xb0, 0xfa, 0x27, 0x05, + 0xe6, 0x84, 0x7f, 0xe2, 0x64, 0x1b, 0x72, 0x95, 0xc9, 0x23, 0x23, 0x31, 0xf8, 0xc8, 0x48, 0x8e, + 0x72, 0x57, 0xa5, 0x06, 0x6c, 0xd4, 0xde, 0xed, 0x34, 0x3e, 0xe8, 0x48, 0xfc, 0x69, 0x62, 0x80, + 0xdd, 0xab, 0x5f, 0x5a, 0xbb, 0xbb, 0x8f, 0x81, 0xf4, 0x75, 0x1d, 0x03, 0x01, 0xcc, 0x1e, 0xfa, + 0xd8, 0xa4, 0x4e, 0x43, 0x23, 0x4f, 0xb0, 0x6f, 0x06, 0xad, 0x7e, 0xc2, 0x8d, 0x50, 0x30, 0x74, + 0x5f, 0x70, 0xe4, 0x57, 0xb3, 0x95, 0xa1, 0x8f, 0x0a, 0xd9, 0x16, 0xef, 0xc0, 0xd4, 0xa6, 0xc3, + 0x0e, 0x15, 0xea, 0xaf, 0x15, 0x28, 0xf6, 0x9b, 0x88, 0x8a, 0x30, 0xee, 0x3e, 0x71, 0x48, 0xf4, + 0xe5, 0x43, 0x0c, 0xd0, 0x19, 0x4c, 0x99, 0xc4, 0x71, 0xed, 0xa8, 0x39, 0x95, 0xb8, 0xe6, 0x2f, + 0x87, 0x59, 0x8e, 0x2e, 0xfa, 0x5c, 0xea, 0x8f, 0x14, 0x98, 0x7f, 0xe8, 0x11, 0xa7, 0x2a, 0xcf, + 0x83, 0xce, 0x2e, 0x8b, 0x01, 0xb3, 0xdd, 0xa7, 0x45, 0xfb, 0x17, 0xc5, 0xe1, 0x5d, 0xd7, 0x5e, + 0x58, 0x6d, 0xc6, 0xed, 0xa1, 0x05, 0x3c, 0x47, 0x3f, 0x55, 0x00, 0xf5, 0xce, 0x1f, 0xe5, 0xa3, + 0xac, 0x0d, 0xb9, 0x0e, 0x13, 0xaf, 0xdd, 0x5d, 0x53, 0xed, 0x36, 0x73, 0x63, 0x9f, 0x0f, 0xbb, + 0x4b, 0x56, 0xff, 0x3f, 0xee, 0x12, 0xf4, 0x16, 0x0c, 0xba, 0x41, 0x64, 0x9f, 0xae, 0xd8, 0xee, + 0x97, 0x5d, 0xc6, 0x5c, 0xc7, 0x5e, 0xaf, 0x58, 0x7c, 0xbf, 0xc8, 0x6e, 0x77, 0xb1, 0x33, 0x05, + 0x3c, 0x2e, 0xa6, 0xfe, 0x58, 0x81, 0x92, 0x46, 0x1a, 0x34, 0x08, 0x89, 0xbf, 0x16, 0x75, 0xac, + 0xa3, 0x2c, 0x5c, 0x85, 0x09, 0x9f, 0xd4, 0x89, 0x4f, 0x44, 0x03, 0x6a, 0xc8, 0x87, 0x29, 0x2d, + 0x9a, 0x88, 0xde, 0x86, 0xc9, 0xb8, 0xf3, 0x7d, 0xd9, 0xe7, 0x2c, 0xad, 0x35, 0x55, 0xfd, 0x83, + 0x02, 0x48, 0x84, 0xf3, 0x18, 0x37, 0xad, 0xb0, 0xcd, 0x84, 0xe8, 0xdb, 0xd8, 0xa5, 0x26, 0xc8, + 0x89, 0x23, 0x54, 0x96, 0x9b, 0xf1, 0xad, 0x99, 0xe4, 0x07, 0xdc, 0xfd, 0xcb, 0x0f, 0x38, 0x6e, + 0x55, 0xe7, 0x95, 0x59, 0xd1, 0x3e, 0x7b, 0xb1, 0xa4, 0x3c, 0x7f, 0xb1, 0xa4, 0xfc, 0xe7, 0xc5, + 0x92, 0xf2, 0x8b, 0x97, 0x4b, 0x63, 0xcf, 0x5f, 0x2e, 0x8d, 0xfd, 0xf3, 0xe5, 0xd2, 0xd8, 0xa3, + 0x77, 0x46, 0xcf, 0xfe, 0xce, 0xff, 0x37, 0x39, 0x49, 0x73, 0xc6, 0xb7, 0xfe, 0x17, 0x00, 0x00, + 0xff, 0xff, 0x24, 0x83, 0xff, 0xe5, 0x95, 0x22, 0x00, 0x00, } func (m *FundingUpdateV1) Marshal() (dAtA []byte, err error) { @@ -4398,6 +4504,61 @@ func (m *UpdatePerpetualEventV1) MarshalToSizedBuffer(dAtA []byte) (int, error) return len(dAtA) - i, nil } +func (m *UpdatePerpetualEventV2) Marshal() (dAtA []byte, err error) { + size := m.Size() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *UpdatePerpetualEventV2) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) +} + +func (m *UpdatePerpetualEventV2) MarshalToSizedBuffer(dAtA []byte) (int, error) { + i := len(dAtA) + _ = i + var l int + _ = l + if m.MarketType != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.MarketType)) + i-- + dAtA[i] = 0x30 + } + if m.LiquidityTier != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.LiquidityTier)) + i-- + dAtA[i] = 0x28 + } + if m.AtomicResolution != 0 { + i = encodeVarintEvents(dAtA, i, uint64((uint32(m.AtomicResolution)<<1)^uint32((m.AtomicResolution>>31)))) + i-- + dAtA[i] = 0x20 + } + if m.MarketId != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.MarketId)) + i-- + dAtA[i] = 0x18 + } + if len(m.Ticker) > 0 { + i -= len(m.Ticker) + copy(dAtA[i:], m.Ticker) + i = encodeVarintEvents(dAtA, i, uint64(len(m.Ticker))) + i-- + dAtA[i] = 0x12 + } + if m.Id != 0 { + i = encodeVarintEvents(dAtA, i, uint64(m.Id)) + i-- + dAtA[i] = 0x8 + } + return len(dAtA) - i, nil +} + func (m *TradingRewardsEventV1) Marshal() (dAtA []byte, err error) { size := m.Size() dAtA = make([]byte, size) @@ -5392,6 +5553,34 @@ func (m *UpdatePerpetualEventV1) Size() (n int) { return n } +func (m *UpdatePerpetualEventV2) Size() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Id != 0 { + n += 1 + sovEvents(uint64(m.Id)) + } + l = len(m.Ticker) + if l > 0 { + n += 1 + l + sovEvents(uint64(l)) + } + if m.MarketId != 0 { + n += 1 + sovEvents(uint64(m.MarketId)) + } + if m.AtomicResolution != 0 { + n += 1 + sozEvents(uint64(m.AtomicResolution)) + } + if m.LiquidityTier != 0 { + n += 1 + sovEvents(uint64(m.LiquidityTier)) + } + if m.MarketType != 0 { + n += 1 + sovEvents(uint64(m.MarketType)) + } + return n +} + func (m *TradingRewardsEventV1) Size() (n int) { if m == nil { return 0 @@ -9441,6 +9630,185 @@ func (m *UpdatePerpetualEventV1) Unmarshal(dAtA []byte) error { } return nil } +func (m *UpdatePerpetualEventV2) Unmarshal(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: UpdatePerpetualEventV2: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: UpdatePerpetualEventV2: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Id", wireType) + } + m.Id = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Id |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Ticker", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLengthEvents + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLengthEvents + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Ticker = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketId", wireType) + } + m.MarketId = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MarketId |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field AtomicResolution", wireType) + } + var v int32 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + v |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + v = int32((uint32(v) >> 1) ^ uint32(((v&1)<<31)>>31)) + m.AtomicResolution = v + case 5: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field LiquidityTier", wireType) + } + m.LiquidityTier = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.LiquidityTier |= uint32(b&0x7F) << shift + if b < 0x80 { + break + } + } + case 6: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field MarketType", wireType) + } + m.MarketType = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflowEvents + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.MarketType |= types.PerpetualMarketType(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skipEvents(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLengthEvents + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *TradingRewardsEventV1) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/protocol/indexer/events/perpetual.go b/protocol/indexer/events/perpetual.go index b23d2c9c99..c6a5db40a2 100644 --- a/protocol/indexer/events/perpetual.go +++ b/protocol/indexer/events/perpetual.go @@ -1,19 +1,26 @@ package events -// NewUpdatePerpetualEventV1 creates a UpdatePerpetualEventV1 representing +import ( + v1 "github.com/dydxprotocol/v4-chain/protocol/indexer/protocol/v1" + perptypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types" +) + +// NewUpdatePerpetualEvent creates a UpdatePerpetualEventV2 representing // update of a perpetual. -func NewUpdatePerpetualEventV1( +func NewUpdatePerpetualEvent( id uint32, ticker string, marketId uint32, atomicResolution int32, liquidityTier uint32, -) *UpdatePerpetualEventV1 { - return &UpdatePerpetualEventV1{ + marketType perptypes.PerpetualMarketType, +) *UpdatePerpetualEventV2 { + return &UpdatePerpetualEventV2{ Id: id, Ticker: ticker, MarketId: marketId, AtomicResolution: atomicResolution, LiquidityTier: liquidityTier, + MarketType: v1.ConvertToPerpetualMarketType(marketType), } } diff --git a/protocol/indexer/events/perpetual_test.go b/protocol/indexer/events/perpetual_test.go index 2a9cc31077..2c9a7cb300 100644 --- a/protocol/indexer/events/perpetual_test.go +++ b/protocol/indexer/events/perpetual_test.go @@ -3,23 +3,28 @@ package events import ( "testing" + v1types "github.com/dydxprotocol/v4-chain/protocol/indexer/protocol/v1/types" + perptypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types" + "github.com/stretchr/testify/require" ) -func TestNewUpdatePerpetualEventV1_Success(t *testing.T) { - updatePerpetualEventV1 := NewUpdatePerpetualEventV1( +func TestNewUpdatePerpetualEvent_Success(t *testing.T) { + updatePerpetualEvent := NewUpdatePerpetualEvent( 5, "BTC-ETH", 5, -8, 2, + perptypes.PerpetualMarketType_PERPETUAL_MARKET_TYPE_CROSS, ) - expectedUpdatePerpetualEventV1Proto := &UpdatePerpetualEventV1{ + expectedUpdatePerpetualEventProto := &UpdatePerpetualEventV2{ Id: 5, Ticker: "BTC-ETH", MarketId: 5, AtomicResolution: -8, LiquidityTier: 2, + MarketType: v1types.PerpetualMarketType_PERPETUAL_MARKET_TYPE_CROSS, } - require.Equal(t, expectedUpdatePerpetualEventV1Proto, updatePerpetualEventV1) + require.Equal(t, expectedUpdatePerpetualEventProto, updatePerpetualEvent) } diff --git a/protocol/testutil/keeper/listing.go b/protocol/testutil/keeper/listing.go index 1448645130..dbe7c61eb3 100644 --- a/protocol/testutil/keeper/listing.go +++ b/protocol/testutil/keeper/listing.go @@ -29,7 +29,6 @@ import ( func ListingKeepers( t testing.TB, bankKeeper bankkeeper.Keeper, - indexerEventManager indexer_manager.IndexerEventManager, ) ( ctx sdk.Context, keeper *keeper.Keeper, @@ -127,6 +126,10 @@ func ListingKeepers( true, ) + mockMsgSender := &mocks.IndexerMessageSender{} + mockMsgSender.On("Enabled").Return(true) + mockIndexerEventManager := indexer_manager.NewIndexerEventManager(mockMsgSender, transientStoreKey, true) + blockTimeKeeper, _ := createBlockTimeKeeper(stateStore, db, cdc) rewardsKeeper, _ := createRewardsKeeper( stateStore, @@ -134,7 +137,7 @@ func ListingKeepers( bankKeeper_out, feeTiersKeeper, pricesKeeper, - indexerEventManager, + mockIndexerEventManager, db, cdc, ) @@ -166,7 +169,7 @@ func ListingKeepers( subaccountsKeeper, revShareKeeper, accountPlusKeeper, - indexerEventManager, + mockIndexerEventManager, transientStoreKey, ) // Create the listing keeper @@ -174,6 +177,7 @@ func ListingKeepers( stateStore, db, cdc, + mockIndexerEventManager, pricesKeeper, perpetualsKeeper, clobKeeper, @@ -194,6 +198,7 @@ func createListingKeeper( stateStore storetypes.CommitMultiStore, db *dbm.MemDB, cdc *codec.ProtoCodec, + indexerEventManager indexer_manager.IndexerEventManager, pricesKeeper *priceskeeper.Keeper, perpetualsKeeper *perpetualskeeper.Keeper, clobKeeper *clobkeeper.Keeper, @@ -215,6 +220,7 @@ func createListingKeeper( []string{ lib.GovModuleAddress.String(), }, + indexerEventManager, pricesKeeper, clobKeeper, marketMapKeeper, diff --git a/protocol/x/listing/keeper/keeper.go b/protocol/x/listing/keeper/keeper.go index 662fea98f4..efab9ca3d8 100644 --- a/protocol/x/listing/keeper/keeper.go +++ b/protocol/x/listing/keeper/keeper.go @@ -7,21 +7,23 @@ import ( storetypes "cosmossdk.io/store/types" "github.com/cosmos/cosmos-sdk/codec" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager" "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/x/listing/types" ) type ( Keeper struct { - cdc codec.BinaryCodec - storeKey storetypes.StoreKey - authorities map[string]struct{} - PricesKeeper types.PricesKeeper - ClobKeeper types.ClobKeeper - MarketMapKeeper types.MarketMapKeeper - PerpetualsKeeper types.PerpetualsKeeper - SubaccountsKeeper types.SubaccountsKeeper - VaultKeeper types.VaultKeeper + cdc codec.BinaryCodec + storeKey storetypes.StoreKey + authorities map[string]struct{} + indexerEventManager indexer_manager.IndexerEventManager + PricesKeeper types.PricesKeeper + ClobKeeper types.ClobKeeper + MarketMapKeeper types.MarketMapKeeper + PerpetualsKeeper types.PerpetualsKeeper + SubaccountsKeeper types.SubaccountsKeeper + VaultKeeper types.VaultKeeper } ) @@ -29,6 +31,7 @@ func NewKeeper( cdc codec.BinaryCodec, storeKey storetypes.StoreKey, authorities []string, + indexerEventsManager indexer_manager.IndexerEventManager, pricesKeeper types.PricesKeeper, clobKeeper types.ClobKeeper, marketMapKeeper types.MarketMapKeeper, @@ -37,15 +40,16 @@ func NewKeeper( vaultKeeper types.VaultKeeper, ) *Keeper { return &Keeper{ - cdc: cdc, - storeKey: storeKey, - authorities: lib.UniqueSliceToSet(authorities), - PricesKeeper: pricesKeeper, - ClobKeeper: clobKeeper, - MarketMapKeeper: marketMapKeeper, - PerpetualsKeeper: perpetualsKeeper, - SubaccountsKeeper: subaccountsKeeper, - VaultKeeper: vaultKeeper, + cdc: cdc, + storeKey: storeKey, + authorities: lib.UniqueSliceToSet(authorities), + indexerEventManager: indexerEventsManager, + PricesKeeper: pricesKeeper, + ClobKeeper: clobKeeper, + MarketMapKeeper: marketMapKeeper, + PerpetualsKeeper: perpetualsKeeper, + SubaccountsKeeper: subaccountsKeeper, + VaultKeeper: vaultKeeper, } } @@ -59,3 +63,7 @@ func (k Keeper) Logger(ctx sdk.Context) log.Logger { } func (k Keeper) InitializeForGenesis(ctx sdk.Context) {} + +func (k Keeper) GetIndexerEventManager() indexer_manager.IndexerEventManager { + return k.indexerEventManager +} diff --git a/protocol/x/listing/keeper/listing.go b/protocol/x/listing/keeper/listing.go index e8329344a8..eddb127bb9 100644 --- a/protocol/x/listing/keeper/listing.go +++ b/protocol/x/listing/keeper/listing.go @@ -6,12 +6,14 @@ import ( "math" "math/big" + "github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager" "github.com/dydxprotocol/v4-chain/protocol/lib/slinky" satypes "github.com/dydxprotocol/v4-chain/protocol/x/subaccounts/types" vaulttypes "github.com/dydxprotocol/v4-chain/protocol/x/vault/types" sdk "github.com/cosmos/cosmos-sdk/types" gogotypes "github.com/cosmos/gogoproto/types" + indexerevents "github.com/dydxprotocol/v4-chain/protocol/indexer/events" clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" "github.com/dydxprotocol/v4-chain/protocol/x/listing/types" perpetualtypes "github.com/dydxprotocol/v4-chain/protocol/x/perpetuals/types" @@ -185,7 +187,28 @@ func (k Keeper) UpgradeIsolatedPerpetualToCross( return err } - // TODO Propagate changes to indexer + // Fetch updated perpetual data after the upgrade + perpetual, err = k.PerpetualsKeeper.GetPerpetual(ctx, perpetualId) + if err != nil { + return err + } + + // Emit indexer event. + k.GetIndexerEventManager().AddTxnEvent( + ctx, + indexerevents.SubtypeUpdatePerpetual, + indexerevents.UpdatePerpetualEventVersion, + indexer_manager.GetBytes( + indexerevents.NewUpdatePerpetualEvent( + perpetual.Params.Id, + perpetual.Params.Ticker, + perpetual.Params.MarketId, + perpetual.Params.AtomicResolution, + perpetual.Params.LiquidityTier, + perpetual.Params.MarketType, + ), + ), + ) return nil } diff --git a/protocol/x/listing/keeper/listing_test.go b/protocol/x/listing/keeper/listing_test.go index 5f75bfb5c0..539dab6a49 100644 --- a/protocol/x/listing/keeper/listing_test.go +++ b/protocol/x/listing/keeper/listing_test.go @@ -17,8 +17,6 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/testutil/constants" - "github.com/stretchr/testify/mock" - "github.com/dydxprotocol/v4-chain/protocol/lib" clobtypes "github.com/dydxprotocol/v4-chain/protocol/x/clob/types" @@ -61,11 +59,9 @@ func TestCreateMarket(t *testing.T) { for name, tc := range tests { t.Run( name, func(t *testing.T) { - mockIndexerEventManager := &mocks.IndexerEventManager{} ctx, keeper, _, _, pricesKeeper, _, _, marketMapKeeper, _, _, _ := keepertest.ListingKeepers( t, &mocks.BankKeeper{}, - mockIndexerEventManager, ) keepertest.CreateTestMarkets(t, ctx, pricesKeeper) @@ -130,11 +126,9 @@ func TestCreatePerpetual(t *testing.T) { for name, tc := range tests { t.Run( name, func(t *testing.T) { - mockIndexerEventManager := &mocks.IndexerEventManager{} ctx, keeper, _, _, pricesKeeper, perpetualsKeeper, _, marketMapKeeper, _, _, _ := keepertest.ListingKeepers( t, &mocks.BankKeeper{}, - mockIndexerEventManager, ) keepertest.CreateLiquidityTiersAndNPerpetuals(t, ctx, perpetualsKeeper, pricesKeeper, 10) @@ -216,20 +210,11 @@ func TestCreateClobPair(t *testing.T) { for name, tc := range tests { t.Run( name, func(t *testing.T) { - mockIndexerEventManager := &mocks.IndexerEventManager{} ctx, keeper, _, _, pricesKeeper, perpetualsKeeper, clobKeeper, marketMapKeeper, _, _, _ := keepertest.ListingKeepers( t, &mocks.BankKeeper{}, - mockIndexerEventManager, ) - mockIndexerEventManager.On( - "AddTxnEvent", - mock.Anything, - mock.Anything, - mock.Anything, - mock.Anything, - ).Return() keepertest.CreateLiquidityTiersAndNPerpetuals(t, ctx, perpetualsKeeper, pricesKeeper, 10) // Set deliverTx mode diff --git a/protocol/x/listing/keeper/msg_server_upgrade_isolated_perpetual_to_cross_test.go b/protocol/x/listing/keeper/msg_server_upgrade_isolated_perpetual_to_cross_test.go index 1ee4846391..bf27627a57 100644 --- a/protocol/x/listing/keeper/msg_server_upgrade_isolated_perpetual_to_cross_test.go +++ b/protocol/x/listing/keeper/msg_server_upgrade_isolated_perpetual_to_cross_test.go @@ -6,6 +6,10 @@ import ( sdkmath "cosmossdk.io/math" sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/gogoproto/proto" + indexerevents "github.com/dydxprotocol/v4-chain/protocol/indexer/events" + "github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager" + v1 "github.com/dydxprotocol/v4-chain/protocol/indexer/protocol/v1" "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/mocks" bank_testutil "github.com/dydxprotocol/v4-chain/protocol/testutil/bank" @@ -77,7 +81,7 @@ func TestMsgUpgradeIsolatedPerpetualToCross(t *testing.T) { crossCollateralPoolBalance: big.NewInt(1), expectedErr: "", }, - "Failure: Empty authority": { + "Failure - empty authority": { msg: &types.MsgUpgradeIsolatedPerpetualToCross{ Authority: "", PerpetualId: 3, // isolated @@ -88,7 +92,7 @@ func TestMsgUpgradeIsolatedPerpetualToCross(t *testing.T) { crossCollateralPoolBalance: big.NewInt(1), expectedErr: "invalid authority", }, - "Failure: Invalid authority": { + "Failure - invalid authority": { msg: &types.MsgUpgradeIsolatedPerpetualToCross{ Authority: "invalid", PerpetualId: 3, // isolated @@ -99,7 +103,7 @@ func TestMsgUpgradeIsolatedPerpetualToCross(t *testing.T) { crossCollateralPoolBalance: big.NewInt(1), expectedErr: "invalid authority", }, - "Failure: Invalid perpetual ID": { + "Failure - invalid perpetual ID": { msg: &types.MsgUpgradeIsolatedPerpetualToCross{ Authority: validAuthority, PerpetualId: 99999999, // invalid @@ -122,13 +126,10 @@ func TestMsgUpgradeIsolatedPerpetualToCross(t *testing.T) { for name, tc := range tests { t.Run( name, func(t *testing.T) { - mockIndexerEventManager := &mocks.IndexerEventManager{} - ctx, keeper, _, _, pricesKeeper, perpetualsKeeper, _, _, assetsKeeper, bankKeeper, subaccountsKeeper := keepertest.ListingKeepers( t, &mocks.BankKeeper{}, - mockIndexerEventManager, ) // Create the default markets. @@ -166,7 +167,6 @@ func TestMsgUpgradeIsolatedPerpetualToCross(t *testing.T) { {isolatedCollateralPoolAddr, tc.isolatedCollateralPoolBalance}, {crossCollateralPoolAddr, tc.crossCollateralPoolBalance}, } - for _, data := range fundingData { addr := data[0].(sdk.AccAddress) amount := data[1].(*big.Int) @@ -210,7 +210,6 @@ func TestMsgUpgradeIsolatedPerpetualToCross(t *testing.T) { {isolatedCollateralPoolAddr, big.NewInt(0)}, {crossCollateralPoolAddr, big.NewInt(0).Add(tc.isolatedCollateralPoolBalance, tc.crossCollateralPoolBalance)}, } - for _, data := range expectedBalances { addr := data[0].(sdk.AccAddress) amount := data[1].(*big.Int) @@ -224,7 +223,44 @@ func TestMsgUpgradeIsolatedPerpetualToCross(t *testing.T) { bankKeeper.GetBalance(ctx, addr, asstypes.AssetUsdc.Denom), ) } + + // Verify that expected indexer event was emitted. + perpetual, err = perpetualsKeeper.GetPerpetual(ctx, tc.msg.PerpetualId) + require.NoError(t, err) + expectedIndexerEvent := &indexerevents.UpdatePerpetualEventV2{ + Id: perpetual.Params.Id, + Ticker: perpetual.Params.Ticker, + MarketId: perpetual.Params.MarketId, + AtomicResolution: perpetual.Params.AtomicResolution, + LiquidityTier: perpetual.Params.LiquidityTier, + MarketType: v1.ConvertToPerpetualMarketType(perpetualtypes.PerpetualMarketType_PERPETUAL_MARKET_TYPE_CROSS), + } + emittedIndexerEvents := getUpdatePerpetualEventsFromIndexerBlock(ctx, keeper) + require.Equal(t, emittedIndexerEvents, []*indexerevents.UpdatePerpetualEventV2{expectedIndexerEvent}) }, ) } } + +// getUpdatePerpetualEventsFromIndexerBlock returns all UpdatePerpetual events from the indexer block. +func getUpdatePerpetualEventsFromIndexerBlock( + ctx sdk.Context, + listingKeeper *listingkeeper.Keeper, +) []*indexerevents.UpdatePerpetualEventV2 { + block := listingKeeper.GetIndexerEventManager().ProduceBlock(ctx) + var updatePerpetualEvents []*indexerevents.UpdatePerpetualEventV2 + for _, event := range block.Events { + if event.Subtype != indexerevents.SubtypeUpdatePerpetual { + continue + } + if _, ok := event.OrderingWithinBlock.(*indexer_manager.IndexerTendermintEvent_TransactionIndex); ok { + var updatePerpetualEvent indexerevents.UpdatePerpetualEventV2 + err := proto.Unmarshal(event.DataBytes, &updatePerpetualEvent) + if err != nil { + panic(err) + } + updatePerpetualEvents = append(updatePerpetualEvents, &updatePerpetualEvent) + } + } + return updatePerpetualEvents +} diff --git a/protocol/x/perpetuals/keeper/perpetual.go b/protocol/x/perpetuals/keeper/perpetual.go index b97c359426..5f3cf9716a 100644 --- a/protocol/x/perpetuals/keeper/perpetual.go +++ b/protocol/x/perpetuals/keeper/perpetual.go @@ -166,12 +166,13 @@ func (k Keeper) ModifyPerpetual( indexerevents.SubtypeUpdatePerpetual, indexerevents.UpdatePerpetualEventVersion, indexer_manager.GetBytes( - indexerevents.NewUpdatePerpetualEventV1( + indexerevents.NewUpdatePerpetualEvent( perpetual.Params.Id, perpetual.Params.Ticker, perpetual.Params.MarketId, perpetual.Params.AtomicResolution, perpetual.Params.LiquidityTier, + perpetual.Params.MarketType, ), ), ) diff --git a/protocol/x/perpetuals/keeper/perpetual_test.go b/protocol/x/perpetuals/keeper/perpetual_test.go index 08e859de1d..a0e99f2c8d 100644 --- a/protocol/x/perpetuals/keeper/perpetual_test.go +++ b/protocol/x/perpetuals/keeper/perpetual_test.go @@ -17,6 +17,7 @@ import ( "github.com/dydxprotocol/v4-chain/protocol/dtypes" indexerevents "github.com/dydxprotocol/v4-chain/protocol/indexer/events" "github.com/dydxprotocol/v4-chain/protocol/indexer/indexer_manager" + v1 "github.com/dydxprotocol/v4-chain/protocol/indexer/protocol/v1" "github.com/dydxprotocol/v4-chain/protocol/lib" "github.com/dydxprotocol/v4-chain/protocol/mocks" big_testutil "github.com/dydxprotocol/v4-chain/protocol/testutil/big" @@ -41,7 +42,7 @@ func TestModifyPerpetual_Success(t *testing.T) { // Create liquidity tiers and perpetuals, perps := keepertest.CreateLiquidityTiersAndNPerpetuals(t, pc.Ctx, pc.PerpetualsKeeper, pc.PricesKeeper, 100) numMarkets := keepertest.GetNumMarkets(t, pc.Ctx, pc.PricesKeeper) - expectedIndexerEvents := make([]*indexerevents.UpdatePerpetualEventV1, len(perps)) + expectedIndexerEvents := make([]*indexerevents.UpdatePerpetualEventV2, len(perps)) for i, item := range perps { // Modify each field arbitrarily and // verify the fields were modified in state. @@ -60,12 +61,13 @@ func TestModifyPerpetual_Success(t *testing.T) { require.NoError(t, err) // Record the indexer event expected to emit from above `ModifyPerpetual`. - expectedIndexerEvents[i] = &indexerevents.UpdatePerpetualEventV1{ + expectedIndexerEvents[i] = &indexerevents.UpdatePerpetualEventV2{ Id: item.Params.Id, Ticker: ticker, MarketId: marketId, AtomicResolution: item.Params.AtomicResolution, LiquidityTier: liquidityTier, + MarketType: v1.ConvertToPerpetualMarketType(item.Params.MarketType), } // Verify updatedp perpetual in store. @@ -112,15 +114,15 @@ func TestModifyPerpetual_Success(t *testing.T) { func getUpdatePerpetualEventsFromIndexerBlock( ctx sdk.Context, perpetualsKeeper *keeper.Keeper, -) []*indexerevents.UpdatePerpetualEventV1 { +) []*indexerevents.UpdatePerpetualEventV2 { block := perpetualsKeeper.GetIndexerEventManager().ProduceBlock(ctx) - var updatePerpetualEvents []*indexerevents.UpdatePerpetualEventV1 + var updatePerpetualEvents []*indexerevents.UpdatePerpetualEventV2 for _, event := range block.Events { if event.Subtype != indexerevents.SubtypeUpdatePerpetual { continue } if _, ok := event.OrderingWithinBlock.(*indexer_manager.IndexerTendermintEvent_TransactionIndex); ok { - var updatePerpetualEvent indexerevents.UpdatePerpetualEventV1 + var updatePerpetualEvent indexerevents.UpdatePerpetualEventV2 err := proto.Unmarshal(event.DataBytes, &updatePerpetualEvent) if err != nil { panic(err)