{"version":3,"file":"IndexerClient.cjs","names":["IndexerBaseClient","QUOTE_PRODUCT_ID","NLP_PRODUCT_ID","ProductEngineType"],"sources":["../src/IndexerClient.ts"],"sourcesContent":["import {\n  NLP_PRODUCT_ID,\n  ProductEngineType,\n  QUOTE_PRODUCT_ID,\n  subaccountFromHex,\n  toBigNumber,\n  toIntegerString,\n} from '@nadohq/shared';\nimport BigNumber from 'bignumber.js';\n\nimport { IndexerBaseClient } from './IndexerBaseClient';\nimport {\n  BaseIndexerPaginatedEvent,\n  CollateralEventType,\n  GetIndexerPaginatedInterestFundingPaymentsResponse,\n  GetIndexerPaginatedLeaderboardParams,\n  GetIndexerPaginatedLeaderboardResponse,\n  GetIndexerPaginatedOrdersParams,\n  GetIndexerPaginatedOrdersResponse,\n  GetIndexerSubaccountCollateralEventsParams,\n  GetIndexerSubaccountCollateralEventsResponse,\n  GetIndexerSubaccountInterestFundingPaymentsParams,\n  GetIndexerSubaccountLiquidationEventsParams,\n  GetIndexerSubaccountLiquidationEventsResponse,\n  GetIndexerSubaccountMatchEventParams,\n  GetIndexerSubaccountMatchEventsResponse,\n  GetIndexerSubaccountNlpEventsParams,\n  GetIndexerSubaccountNlpEventsResponse,\n  GetIndexerSubaccountSettlementEventsParams,\n  GetIndexerSubaccountSettlementEventsResponse,\n  IndexerCollateralEvent,\n  IndexerEventPerpStateSnapshot,\n  IndexerEventSpotStateSnapshot,\n  IndexerEventWithTx,\n  IndexerLiquidationEvent,\n  IndexerNlpEvent,\n  IndexerSettlementEvent,\n  NadoLiquidateSubaccountTx,\n  PaginatedIndexerEventsResponse,\n} from './types';\n\n/**\n * Indexer client providing paginated queries for historical data from the Nado indexer service\n */\nexport class IndexerClient extends IndexerBaseClient {\n  async getPaginatedSubaccountMatchEvents(\n    params: GetIndexerSubaccountMatchEventParams,\n  ): Promise<GetIndexerSubaccountMatchEventsResponse> {\n    const {\n      startCursor,\n      maxTimestampInclusive,\n      limit: requestedLimit,\n      subaccountName,\n      subaccountOwner,\n      isolated,\n      productIds,\n    } = params;\n\n    const limit = requestedLimit + 1;\n    const events = await this.getMatchEvents({\n      startCursor,\n      maxTimestampInclusive,\n      limit,\n      subaccounts: [{ subaccountName, subaccountOwner }],\n      productIds,\n      isolated,\n    });\n\n    return this.getPaginationEventsResponse(events, requestedLimit);\n  }\n\n  async getPaginatedSubaccountNlpEvents(\n    params: GetIndexerSubaccountNlpEventsParams,\n  ): Promise<GetIndexerSubaccountNlpEventsResponse> {\n    const {\n      startCursor,\n      maxTimestampInclusive,\n      limit: requestedLimit,\n      subaccountName,\n      subaccountOwner,\n    } = params;\n\n    // There are 2 events per mint/burn for spot - one associated with the NLP product & the other with the primary quote\n    const limit = requestedLimit + 1;\n    const baseResponse = await this.getEvents({\n      startCursor,\n      maxTimestampInclusive,\n      eventTypes: ['mint_nlp', 'burn_nlp'],\n      limit: {\n        type: 'txs',\n        value: limit,\n      },\n      subaccounts: [{ subaccountName, subaccountOwner }],\n    });\n\n    // Now aggregate results by the submission index, use map to maintain insertion order\n    const eventsBySubmissionIdx = new Map<string, IndexerNlpEvent>();\n\n    baseResponse.forEach((event) => {\n      const mappedEvent = (() => {\n        const existingEvent = eventsBySubmissionIdx.get(event.submissionIndex);\n        if (existingEvent) {\n          return existingEvent;\n        }\n\n        const newEvent: IndexerNlpEvent = {\n          nlpDelta: toBigNumber(0),\n          primaryQuoteDelta: toBigNumber(0),\n          timestamp: event.timestamp,\n          submissionIndex: event.submissionIndex,\n          tx: event.tx,\n          ...subaccountFromHex(event.subaccount),\n        };\n        eventsBySubmissionIdx.set(event.submissionIndex, newEvent);\n\n        return newEvent;\n      })();\n\n      const balanceDelta = event.state.postBalance.amount.minus(\n        event.state.preBalance.amount,\n      );\n\n      const productId = event.state.market.productId;\n      if (productId === QUOTE_PRODUCT_ID) {\n        mappedEvent.primaryQuoteDelta = balanceDelta;\n      } else if (productId === NLP_PRODUCT_ID) {\n        mappedEvent.nlpDelta = balanceDelta;\n      } else {\n        throw Error(`Invalid product ID for NLP event ${productId}`);\n      }\n    });\n\n    // Force cast to get rid of the `Partial`\n    const events = Array.from(eventsBySubmissionIdx.values());\n    return this.getPaginationEventsResponse(events, requestedLimit);\n  }\n\n  async getPaginatedSubaccountCollateralEvents(\n    params: GetIndexerSubaccountCollateralEventsParams,\n  ): Promise<GetIndexerSubaccountCollateralEventsResponse> {\n    const {\n      startCursor,\n      maxTimestampInclusive,\n      limit: requestedLimit,\n      subaccountName,\n      subaccountOwner,\n      eventTypes,\n      isolated,\n    } = params;\n\n    const limit = requestedLimit + 1;\n    const baseResponse = await this.getEvents({\n      startCursor,\n      maxTimestampInclusive,\n      eventTypes: eventTypes ?? [\n        'deposit_collateral',\n        'withdraw_collateral',\n        'withdraw_collateral_v2',\n        'transfer_quote',\n        'transfer_quote_v2',\n      ],\n      limit: {\n        type: 'txs',\n        value: limit,\n      },\n      subaccounts: [{ subaccountName, subaccountOwner }],\n      isolated,\n    });\n\n    const events = baseResponse.map((event): IndexerCollateralEvent => {\n      if (event.state.type !== ProductEngineType.SPOT) {\n        throw Error('Incorrect event state for collateral event');\n      }\n\n      return {\n        timestamp: event.timestamp,\n        // This cast is safe as the query param restricts to collateral events\n        eventType: event.eventType as CollateralEventType,\n        submissionIndex: event.submissionIndex,\n        snapshot: event.state,\n        amount: event.state.postBalance.amount.minus(\n          event.state.preBalance.amount,\n        ),\n        newAmount: event.state.postBalance.amount,\n        tx: event.tx,\n        ...subaccountFromHex(event.subaccount),\n      };\n    });\n\n    return this.getPaginationEventsResponse(events, requestedLimit);\n  }\n\n  async getPaginatedSubaccountOrders(\n    params: GetIndexerPaginatedOrdersParams,\n  ): Promise<GetIndexerPaginatedOrdersResponse> {\n    const {\n      startCursor,\n      maxTimestampInclusive,\n      limit: requestedLimit,\n      subaccountName,\n      subaccountOwner,\n      productIds,\n      triggerTypes,\n      isolated,\n    } = params;\n\n    const limit = requestedLimit + 1;\n    const baseResponse = await this.getOrders({\n      startCursor,\n      maxTimestampInclusive,\n      subaccounts: [{ subaccountName, subaccountOwner }],\n      limit,\n      productIds,\n      triggerTypes,\n      isolated,\n    });\n\n    // Same pagination meta logic as events, but duplicate for now as this return type is slightly different\n    const truncatedOrders = baseResponse.slice(0, requestedLimit);\n    const hasMore = baseResponse.length > truncatedOrders.length;\n    return {\n      meta: {\n        hasMore,\n        nextCursor: baseResponse[truncatedOrders.length]?.submissionIndex,\n      },\n      orders: truncatedOrders,\n    };\n  }\n\n  async getPaginatedSubaccountSettlementEvents(\n    params: GetIndexerSubaccountSettlementEventsParams,\n  ): Promise<GetIndexerSubaccountSettlementEventsResponse> {\n    const {\n      startCursor,\n      maxTimestampInclusive,\n      limit: requestedLimit,\n      subaccountName,\n      subaccountOwner,\n    } = params;\n\n    // Each settlement has a quote & perp balance change, so 2 events per settlement tx\n    const limit = requestedLimit + 1;\n    const baseResponse = await this.getEvents({\n      startCursor,\n      maxTimestampInclusive,\n      eventTypes: ['settle_pnl'],\n      limit: {\n        type: 'txs',\n        value: limit,\n      },\n      subaccounts: [{ subaccountName, subaccountOwner }],\n    });\n\n    const events = baseResponse\n      .map((event): IndexerSettlementEvent | undefined => {\n        if (event.state.market.productId === QUOTE_PRODUCT_ID) {\n          return;\n        }\n        if (event.state.type !== ProductEngineType.PERP) {\n          throw Error('Incorrect event state for settlement event');\n        }\n\n        return {\n          timestamp: event.timestamp,\n          submissionIndex: event.submissionIndex,\n          snapshot: event.state,\n          // Spot quote delta = -vQuote delta\n          quoteDelta: event.state.preBalance.vQuoteBalance.minus(\n            event.state.postBalance.vQuoteBalance,\n          ),\n          isolated: event.isolated,\n          tx: event.tx,\n          ...subaccountFromHex(event.subaccount),\n        };\n      })\n      .filter((event): event is IndexerSettlementEvent => !!event);\n\n    return this.getPaginationEventsResponse(events, requestedLimit);\n  }\n\n  async getPaginatedSubaccountLiquidationEvents(\n    params: GetIndexerSubaccountLiquidationEventsParams,\n  ): Promise<GetIndexerSubaccountLiquidationEventsResponse> {\n    const {\n      startCursor,\n      maxTimestampInclusive,\n      limit: requestedLimit,\n      subaccountName,\n      subaccountOwner,\n      productIds,\n    } = params;\n\n    // There is 1 event emitted per product, including quote\n    // However, if the balance change is 0, then the liquidation did not touch the product\n    // A tx operates on a given health group, so only a spot & its associated perp can be actually liquidated within a single tx\n    // with an associated quote balance change\n    const limit = requestedLimit + 1;\n    const baseResponse = await this.getEvents({\n      startCursor,\n      maxTimestampInclusive,\n      eventTypes: ['liquidate_subaccount'],\n      limit: {\n        type: 'txs',\n        value: limit,\n      },\n      subaccounts: [{ subaccountName, subaccountOwner }],\n      productIds,\n    });\n\n    // Now aggregate results by the submission index, use map to maintain insertion order\n    const eventsBySubmissionIdx = new Map<\n      string,\n      Partial<IndexerLiquidationEvent>\n    >();\n\n    const productIdsSet = productIds ? new Set(productIds) : undefined;\n    baseResponse.forEach((event) => {\n      // even though we're querying for a specific set of product IDs\n      // backend will have events that are associated with every product\n      // because they generate a single event per product for each liquidation\n      // as a result, we need to filter out events that are not relevant to the requested product IDs\n      if (\n        productIdsSet &&\n        !productIdsSet.has(\n          // product_id can also encode a health group for spread liquidation, but we ignore\n          // this case for now\n          (event.tx as NadoLiquidateSubaccountTx).liquidate_subaccount\n            .product_id,\n        )\n      ) {\n        return;\n      }\n\n      const mappedEvent = (() => {\n        const existingEvent = eventsBySubmissionIdx.get(event.submissionIndex);\n        if (existingEvent) {\n          return existingEvent;\n        }\n\n        const newEvent: Partial<IndexerLiquidationEvent> = {\n          perp: undefined,\n          spot: undefined,\n          quote: undefined,\n          timestamp: event.timestamp,\n          submissionIndex: event.submissionIndex,\n        };\n\n        return newEvent;\n      })();\n\n      // The original balance is the negated delta\n      const balanceDelta = event.state.postBalance.amount.minus(\n        event.state.preBalance.amount,\n      );\n\n      // Event without balance change - not part of this liq\n      // However, we could have zero balance changes for the quote product if this was a partial liquidation\n      if (\n        balanceDelta.isZero() &&\n        event.state.market.productId !== QUOTE_PRODUCT_ID\n      ) {\n        return;\n      }\n\n      if (event.state.type === ProductEngineType.PERP) {\n        mappedEvent.perp = {\n          amountLiquidated: balanceDelta.negated(),\n          // This cast is safe because we're checking for event.state.type\n          indexerEvent:\n            event as IndexerEventWithTx<IndexerEventPerpStateSnapshot>,\n        };\n      } else if (event.state.market.productId === QUOTE_PRODUCT_ID) {\n        mappedEvent.quote = {\n          balanceDelta,\n          indexerEvent:\n            event as IndexerEventWithTx<IndexerEventSpotStateSnapshot>,\n        };\n      } else {\n        mappedEvent.spot = {\n          amountLiquidated: balanceDelta.negated(),\n          indexerEvent:\n            event as IndexerEventWithTx<IndexerEventSpotStateSnapshot>,\n        };\n      }\n\n      eventsBySubmissionIdx.set(event.submissionIndex, mappedEvent);\n    });\n\n    // Force cast to get rid of the `Partial`\n    const events = Array.from(\n      eventsBySubmissionIdx.values(),\n    ) as IndexerLiquidationEvent[];\n    return this.getPaginationEventsResponse(events, requestedLimit);\n  }\n\n  /**\n   * Get all interest funding payments for a given subaccount with the standard pagination response\n   * This is a simple wrapper over the underlying `getInterestFundingPayments` function. Very little\n   * additional processing is needed because the endpoint is well structured for pagination\n   *\n   * @param params\n   */\n  async getPaginatedSubaccountInterestFundingPayments(\n    params: GetIndexerSubaccountInterestFundingPaymentsParams,\n  ): Promise<GetIndexerPaginatedInterestFundingPaymentsResponse> {\n    const {\n      limit,\n      productIds,\n      startCursor,\n      maxTimestampInclusive,\n      subaccountName,\n      subaccountOwner,\n    } = params;\n    const baseResponse = await this.getInterestFundingPayments({\n      limit,\n      productIds,\n      startCursor,\n      maxTimestampInclusive,\n      subaccount: {\n        subaccountName,\n        subaccountOwner,\n      },\n    });\n\n    return {\n      ...baseResponse,\n      meta: {\n        hasMore: baseResponse.nextCursor != null,\n        nextCursor: baseResponse.nextCursor ?? undefined,\n      },\n    };\n  }\n\n  /**\n   * Paginated leaderboard query that paginates on rank number.\n   *\n   * @param params\n   */\n  async getPaginatedLeaderboard(\n    params: GetIndexerPaginatedLeaderboardParams,\n  ): Promise<GetIndexerPaginatedLeaderboardResponse> {\n    const requestedLimit = params.limit;\n\n    const baseResponse = await this.getLeaderboard({\n      contestId: params.contestId,\n      rankType: params.rankType,\n      // Query for 1 more result for proper pagination\n      limit: requestedLimit + 1,\n      // Start cursor is the next rank number\n      startCursor: params.startCursor,\n    });\n\n    const overflowParticipant = baseResponse.participants[requestedLimit];\n    let nextCursor: BigNumber | undefined;\n    if (overflowParticipant) {\n      // If rankType specified, use it directly. Otherwise it's a single-track\n      // contest so grab the rank from the only track present.\n      const trackData = (\n        params.rankType\n          ? overflowParticipant.tracks[params.rankType]\n          : Object.values(overflowParticipant.tracks)[0]\n      )!;\n      nextCursor = trackData.rank;\n    }\n\n    return {\n      ...baseResponse,\n      // Truncate the response to the requested limit\n      participants: baseResponse.participants.slice(0, requestedLimit),\n      meta: {\n        hasMore: baseResponse.participants.length > requestedLimit,\n        nextCursor:\n          nextCursor !== undefined ? toIntegerString(nextCursor) : undefined,\n      },\n    };\n  }\n\n  /**\n   * A util function to generate the standard pagination response for events\n   * @param events\n   * @param requestedLimit given by consumers of the SDK\n   * @private\n   */\n  private getPaginationEventsResponse<T extends BaseIndexerPaginatedEvent>(\n    events: T[],\n    requestedLimit: number,\n  ): PaginatedIndexerEventsResponse<T> {\n    const truncatedEvents = events.slice(0, requestedLimit);\n    const hasMore = events.length > truncatedEvents.length;\n\n    return {\n      events: truncatedEvents,\n      meta: {\n        hasMore,\n        // We want the NEXT available cursor, so we use the first event after the truncation cutoff\n        // If len(events) === len(truncatedEvents), there are no more entries and this is undefined\n        nextCursor: events[truncatedEvents.length]?.submissionIndex,\n      },\n    };\n  }\n}\n"],"mappings":"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"}