diff --git a/packages/indexer-nibi/src/defaultObjects.ts b/packages/indexer-nibi/src/defaultObjects.ts index 8b9b6cdf..ab6a7531 100644 --- a/packages/indexer-nibi/src/defaultObjects.ts +++ b/packages/indexer-nibi/src/defaultObjects.ts @@ -108,5 +108,5 @@ export const defaultSpotPool = { block: defaultBlock, pool: defaultPool, pool_shares: defaultTokenAsString, - user_address: "", + user: defaultUser, } diff --git a/packages/indexer-nibi/src/gql.ts b/packages/indexer-nibi/src/gql.ts index 4d02934c..efd1d312 100644 --- a/packages/indexer-nibi/src/gql.ts +++ b/packages/indexer-nibi/src/gql.ts @@ -71,7 +71,8 @@ export const cleanResponse = async (rawResp: Response) => { export const gqlQuery = ( name: string, typedQueryArgs: { [key: string]: T }, - properties: string + properties: string, + excludeParentObject?: boolean ) => { let queryArgList = [] @@ -104,11 +105,11 @@ export const gqlQuery = ( const hasQueryList = (char: string) => (queryArgList.length > 0 ? char : "") - return `{ + return `${excludeParentObject ? "" : "{"} ${name} ${hasQueryList("(")}${queryArgList.join(", ")}${hasQueryList(")")} { ${properties} } - }` + ${excludeParentObject ? "" : "}"}` } export const doGqlQuery = async (gqlQuery: string, gqlEndpt: string) => { diff --git a/packages/indexer-nibi/src/gql/generated.ts b/packages/indexer-nibi/src/gql/generated.ts index 371162d3..cfe15b09 100644 --- a/packages/indexer-nibi/src/gql/generated.ts +++ b/packages/indexer-nibi/src/gql/generated.ts @@ -25,6 +25,7 @@ export type Scalars = { Boolean: { input: boolean; output: boolean } Int: { input: number; output: number } Float: { input: number; output: number } + Time: { input: any; output: any } } export type Block = { @@ -35,10 +36,12 @@ export type Block = { readonly num_txs: Scalars["Int"]["output"] } -export type CommunityPoolToken = { - readonly __typename?: "CommunityPoolToken" - readonly amount: Scalars["Float"]["output"] - readonly denom: Scalars["String"]["output"] +export type CommunityPoolFilter = { + readonly denom?: InputMaybe +} + +export enum CommunityPoolOrder { + Denom = "denom", } export type Delegation = { @@ -60,18 +63,92 @@ export enum DelegationOrder { export type DistributionCommission = { readonly __typename?: "DistributionCommission" - readonly commission?: Maybe> + readonly commission?: Maybe> readonly validator: Validator } export type DistributionCommissionFilter = { - readonly validator_address: Scalars["String"]["input"] + readonly validator_address?: InputMaybe } export enum DistributionCommissionOrder { ValidatorAddress = "validator_address", } +export type FloatToken = { + readonly __typename?: "FloatToken" + readonly amount: Scalars["Float"]["output"] + readonly denom: Scalars["String"]["output"] +} + +export type MarkPriceCandle = { + readonly __typename?: "MarkPriceCandle" + readonly close: Scalars["Float"]["output"] + readonly high: Scalars["Float"]["output"] + readonly low: Scalars["Float"]["output"] + readonly open: Scalars["Float"]["output"] + readonly pair: Scalars["String"]["output"] + readonly period: Scalars["Int"]["output"] + readonly periodStartTs: Scalars["Time"]["output"] +} + +export type MarkPriceCandlesFilter = { + readonly pairEq?: InputMaybe + readonly periodEq?: InputMaybe + readonly periodGt?: InputMaybe + readonly periodGte?: InputMaybe + readonly periodLt?: InputMaybe + readonly periodLte?: InputMaybe + readonly periodStartTsEq?: InputMaybe + readonly periodStartTsGt?: InputMaybe + readonly periodStartTsGte?: InputMaybe + readonly periodStartTsLt?: InputMaybe + readonly periodStartTsLte?: InputMaybe +} + +export enum MarkPriceCandlesOrder { + Period = "period", + PeriodStartTs = "periodStartTs", +} + +export type PeriodFilter = { + readonly periodEq?: InputMaybe + readonly periodGt?: InputMaybe + readonly periodGte?: InputMaybe + readonly periodLt?: InputMaybe + readonly periodLte?: InputMaybe + readonly periodStartTsEq?: InputMaybe + readonly periodStartTsGt?: InputMaybe + readonly periodStartTsGte?: InputMaybe + readonly periodStartTsLt?: InputMaybe + readonly periodStartTsLte?: InputMaybe +} + +export enum PeriodOrder { + Period = "period", + PeriodStartTs = "period_start_ts", +} + +export type PerpLeaderboard = { + readonly __typename?: "PerpLeaderboard" + readonly avg_pct_pnl: Scalars["Float"]["output"] + readonly input_margin: Scalars["Float"]["output"] + readonly raw_pnl: Scalars["Float"]["output"] + readonly raw_pnl_with_unrealized: Scalars["Float"]["output"] + readonly trader_address: Scalars["String"]["output"] +} + +export type PerpLeaderboardFilter = { + readonly trader_address?: InputMaybe +} + +export enum PerpLeaderboardOrder { + AvgPctPnl = "avg_pct_pnl", + RawPnl = "raw_pnl", + RawPnlWithUnrealized = "raw_pnl_with_unrealized", + TraderAddress = "trader_address", +} + export type PerpMarket = { readonly __typename?: "PerpMarket" readonly base_reserve: Scalars["Float"]["output"] @@ -137,9 +214,11 @@ export enum PerpPositionOrder { export type Query = { readonly __typename?: "Query" - readonly communityPool: ReadonlyArray + readonly communityPool: ReadonlyArray readonly delegations: ReadonlyArray readonly distributionCommissions: ReadonlyArray + readonly markPriceCandles: ReadonlyArray + readonly perpLeaderboard: ReadonlyArray readonly perpMarket?: Maybe readonly perpMarkets: ReadonlyArray readonly perpPosition?: Maybe @@ -151,13 +230,17 @@ export type Query = { readonly spotPoolJoined: ReadonlyArray readonly spotPoolSwap: ReadonlyArray readonly spotPools: ReadonlyArray + readonly stats: Stats readonly unbondings: ReadonlyArray readonly users: ReadonlyArray readonly validators: ReadonlyArray } export type QueryCommunityPoolArgs = { - denom?: InputMaybe + limit?: InputMaybe + order_by?: InputMaybe + order_desc?: InputMaybe + where?: InputMaybe } export type QueryDelegationsArgs = { @@ -174,8 +257,22 @@ export type QueryDistributionCommissionsArgs = { where?: InputMaybe } +export type QueryMarkPriceCandlesArgs = { + limit?: InputMaybe + order_by?: InputMaybe + order_desc?: InputMaybe + where?: InputMaybe +} + +export type QueryPerpLeaderboardArgs = { + limit?: InputMaybe + order_by?: InputMaybe + order_desc?: InputMaybe + where?: InputMaybe +} + export type QueryPerpMarketArgs = { - pair: Scalars["String"]["input"] + where?: InputMaybe } export type QueryPerpMarketsArgs = { @@ -186,8 +283,7 @@ export type QueryPerpMarketsArgs = { } export type QueryPerpPositionArgs = { - pair: Scalars["String"]["input"] - trader_address: Scalars["String"]["input"] + where?: InputMaybe } export type QueryPerpPositionsArgs = { @@ -336,7 +432,7 @@ export type SpotPoolCreated = { readonly block: Block readonly pool: SpotPool readonly pool_shares: SharesToken - readonly user_address: Scalars["String"]["output"] + readonly user: User } export type SpotPoolCreatedFilter = { @@ -354,7 +450,7 @@ export type SpotPoolExited = { readonly block: Block readonly pool: SpotPool readonly pool_shares: SharesToken - readonly user_address: Scalars["String"]["output"] + readonly user: User } export type SpotPoolExitedFilter = { @@ -376,7 +472,7 @@ export type SpotPoolJoined = { readonly block: Block readonly pool: SpotPool readonly pool_shares: SharesToken - readonly user_address: Scalars["String"]["output"] + readonly user: User } export type SpotPoolJoinedFilter = { @@ -399,7 +495,7 @@ export type SpotPoolSwap = { readonly pool: SpotPool readonly token_in: Token readonly token_out: Token - readonly user_address: Scalars["String"]["output"] + readonly user: User } export type SpotPoolSwapFilter = { @@ -416,6 +512,243 @@ export enum SpotPoolSwapOrder { UserAddress = "user_address", } +export type Stats = { + readonly __typename?: "Stats" + readonly fees: ReadonlyArray + readonly perpOpenInterest: ReadonlyArray + readonly perpPnl: ReadonlyArray + readonly totals: ReadonlyArray + readonly tvl: ReadonlyArray + readonly users: ReadonlyArray + readonly volume: ReadonlyArray +} + +export type StatsFeesArgs = { + limit?: InputMaybe + order?: InputMaybe + orderDesc?: InputMaybe + where?: InputMaybe +} + +export type StatsPerpOpenInterestArgs = { + limit?: InputMaybe + order?: InputMaybe + orderDesc?: InputMaybe + where?: InputMaybe +} + +export type StatsPerpPnlArgs = { + limit?: InputMaybe + order?: InputMaybe + orderDesc?: InputMaybe + where?: InputMaybe +} + +export type StatsTotalsArgs = { + limit?: InputMaybe + order?: InputMaybe + orderDesc?: InputMaybe + where?: InputMaybe +} + +export type StatsTvlArgs = { + limit?: InputMaybe + order?: InputMaybe + orderDesc?: InputMaybe + where?: InputMaybe +} + +export type StatsUsersArgs = { + limit?: InputMaybe + order?: InputMaybe + orderDesc?: InputMaybe + where?: InputMaybe +} + +export type StatsVolumeArgs = { + limit?: InputMaybe + order?: InputMaybe + orderDesc?: InputMaybe + where?: InputMaybe +} + +export type StatsFees = { + readonly __typename?: "StatsFees" + readonly feesLiquidations: Scalars["Float"]["output"] + readonly feesLiquidationsCumulative: Scalars["Float"]["output"] + readonly feesPerp: Scalars["Float"]["output"] + readonly feesPerpCumulative: Scalars["Float"]["output"] + readonly feesSwap: Scalars["Float"]["output"] + readonly feesSwapCumulative: Scalars["Float"]["output"] + readonly feesTotal: Scalars["Float"]["output"] + readonly feesTotalCumulative: Scalars["Float"]["output"] + readonly period: Scalars["Int"]["output"] + readonly periodStartTs: Scalars["Time"]["output"] +} + +export enum StatsFeesOrder { + FeesLiquidations = "fees_liquidations", + FeesLiquidationsCumulative = "fees_liquidations_cumulative", + FeesPerp = "fees_perp", + FeesPerpCumulative = "fees_perp_cumulative", + FeesSwap = "fees_swap", + FeesSwapCumulative = "fees_swap_cumulative", + FeesTotal = "fees_total", + FeesTotalCumulative = "fees_total_cumulative", + Period = "period", + PeriodStartTs = "period_start_ts", +} + +export type StatsPerpOpenInterest = { + readonly __typename?: "StatsPerpOpenInterest" + readonly openInterestLong: Scalars["Float"]["output"] + readonly openInterestShort: Scalars["Float"]["output"] + readonly openInterestTotal: Scalars["Float"]["output"] + readonly period: Scalars["Int"]["output"] + readonly periodStartTs: Scalars["Time"]["output"] +} + +export enum StatsPerpOpenInterestOrder { + OpenInterestLong = "open_interest_long", + OpenInterestShort = "open_interest_short", + OpenInterestTotal = "open_interest_total", + Period = "period", + PeriodStartTs = "period_start_ts", +} + +export type StatsPerpPnl = { + readonly __typename?: "StatsPerpPnl" + readonly loss: Scalars["Float"]["output"] + readonly lossCumulative: Scalars["Float"]["output"] + readonly netPnl: Scalars["Float"]["output"] + readonly netPnlCumulative: Scalars["Float"]["output"] + readonly period: Scalars["Int"]["output"] + readonly periodStartTs: Scalars["Time"]["output"] + readonly profit: Scalars["Float"]["output"] + readonly profitCumulative: Scalars["Float"]["output"] +} + +export enum StatsPerpPnlOrder { + Loss = "loss", + LossCumulative = "loss_cumulative", + NetPnl = "net_pnl", + NetPnlCumulative = "net_pnl_cumulative", + Period = "period", + PeriodStartTs = "period_start_ts", + Profit = "profit", + ProfitCumulative = "profit_cumulative", +} + +export type StatsTotals = { + readonly __typename?: "StatsTotals" + readonly period: Scalars["Int"]["output"] + readonly periodStartTs: Scalars["Time"]["output"] + readonly totalFeesLiquidations: Scalars["Float"]["output"] + readonly totalFeesPerp: Scalars["Float"]["output"] + readonly totalOpenInterest: Scalars["Float"]["output"] + readonly totalPerp: Scalars["Float"]["output"] + readonly totalSwap: Scalars["Float"]["output"] + readonly totalTvl: Scalars["Float"]["output"] +} + +export enum StatsTotalsOrder { + Period = "period", + PeriodStartTs = "period_start_ts", + TotalFeesLiquidations = "total_fees_liquidations", + TotalFeesPerp = "total_fees_perp", + TotalOpenInterest = "total_open_interest", + TotalPerp = "total_perp", + TotalSwap = "total_swap", + TotalTvl = "total_tvl", +} + +export type StatsTvl = { + readonly __typename?: "StatsTvl" + readonly period: Scalars["Int"]["output"] + readonly periodStartTs: Scalars["Time"]["output"] + readonly tvlPerp: Scalars["Float"]["output"] + readonly tvlStablecoin: Scalars["Float"]["output"] + readonly tvlStaking: Scalars["Float"]["output"] + readonly tvlSwap: Scalars["Float"]["output"] + readonly tvlTotal: Scalars["Float"]["output"] +} + +export enum StatsTvlOrder { + Period = "period", + PeriodStartTs = "period_start_ts", + TvlPerp = "tvl_perp", + TvlStablecoin = "tvl_stablecoin", + TvlStaking = "tvl_staking", + TvlSwap = "tvl_swap", + TvlTotal = "tvl_total", +} + +export type StatsUsers = { + readonly __typename?: "StatsUsers" + readonly newUsersLp: Scalars["Int"]["output"] + readonly newUsersLpCumulative: Scalars["Int"]["output"] + readonly newUsersPerp: Scalars["Int"]["output"] + readonly newUsersPerpCumulative: Scalars["Int"]["output"] + readonly newUsersSwap: Scalars["Int"]["output"] + readonly newUsersSwapCumulative: Scalars["Int"]["output"] + readonly newUsersTotal: Scalars["Int"]["output"] + readonly newUsersTotalCumulative: Scalars["Int"]["output"] + readonly period: Scalars["Int"]["output"] + readonly periodStartTs: Scalars["Time"]["output"] + readonly uniqueUsersLp: Scalars["Int"]["output"] + readonly uniqueUsersPerp: Scalars["Int"]["output"] + readonly uniqueUsersSwap: Scalars["Int"]["output"] + readonly uniqueUsersTotal: Scalars["Int"]["output"] + readonly userActionsLp: Scalars["Int"]["output"] + readonly userActionsPerp: Scalars["Int"]["output"] + readonly userActionsSwap: Scalars["Int"]["output"] + readonly userActionsTotal: Scalars["Int"]["output"] +} + +export enum StatsUsersOrder { + NewUsersLp = "new_users_lp", + NewUsersLpCumulative = "new_users_lp_cumulative", + NewUsersPerp = "new_users_perp", + NewUsersPerpCumulative = "new_users_perp_cumulative", + NewUsersSwap = "new_users_swap", + NewUsersSwapCumulative = "new_users_swap_cumulative", + NewUsersTotal = "new_users_total", + NewUsersTotalCumulative = "new_users_total_cumulative", + Period = "period", + PeriodStartTs = "period_start_ts", + UniqueUsersLp = "unique_users_lp", + UniqueUsersPerp = "unique_users_perp", + UniqueUsersSwap = "unique_users_swap", + UniqueUsersTotal = "unique_users_total", + UserActionsLp = "user_actions_lp", + UserActionsPerp = "user_actions_perp", + UserActionsSwap = "user_actions_swap", + UserActionsTotal = "user_actions_total", +} + +export type StatsVolume = { + readonly __typename?: "StatsVolume" + readonly period: Scalars["Int"]["output"] + readonly periodStartTs: Scalars["Time"]["output"] + readonly volumePerp: Scalars["Float"]["output"] + readonly volumePerpCumulative: Scalars["Float"]["output"] + readonly volumeSwap: Scalars["Float"]["output"] + readonly volumeSwapCumulative: Scalars["Float"]["output"] + readonly volumeTotal: Scalars["Float"]["output"] + readonly volumeTotalCumulative: Scalars["Float"]["output"] +} + +export enum StatsVolumeOrder { + Period = "period", + PeriodStartTs = "period_start_ts", + VolumePerp = "volume_perp", + VolumePerpCumulative = "volume_perp_cumulative", + VolumeSwap = "volume_swap", + VolumeSwapCumulative = "volume_swap_cumulative", + VolumeTotal = "volume_total", + VolumeTotalCumulative = "volume_total_cumulative", +} + export type Token = { readonly __typename?: "Token" readonly amount: Scalars["Int"]["output"] diff --git a/packages/indexer-nibi/src/gql/schema.graphql b/packages/indexer-nibi/src/gql/schema.graphql index 182fbbb5..47dd9733 100644 --- a/packages/indexer-nibi/src/gql/schema.graphql +++ b/packages/indexer-nibi/src/gql/schema.graphql @@ -1,3 +1,8 @@ +directive @goModel( + model: String + models: [String!] +) on ENUM | INPUT_OBJECT | INTERFACE | OBJECT | SCALAR | UNION + type Block { block: Int! block_duration: Float! @@ -5,9 +10,12 @@ type Block { num_txs: Int! } -type CommunityPoolToken { - amount: Float! - denom: String! +input CommunityPoolFilter { + denom: String +} + +enum CommunityPoolOrder { + denom } type Delegation { @@ -27,18 +35,89 @@ enum DelegationOrder { } type DistributionCommission { - commission: [Token!] + commission: [FloatToken!] validator: Validator! } input DistributionCommissionFilter { - validator_address: String! + validator_address: String } enum DistributionCommissionOrder { validator_address } +type FloatToken { + amount: Float! + denom: String! +} + +type MarkPriceCandle { + close: Float! + high: Float! + low: Float! + open: Float! + pair: String! + period: Int! + periodStartTs: Time! +} + +input MarkPriceCandlesFilter { + pairEq: String + periodEq: Int + periodGt: Int + periodGte: Int + periodLt: Int + periodLte: Int + periodStartTsEq: Time + periodStartTsGt: Time + periodStartTsGte: Time + periodStartTsLt: Time + periodStartTsLte: Time +} + +enum MarkPriceCandlesOrder { + period + periodStartTs +} + +input PeriodFilter { + periodEq: Int + periodGt: Int + periodGte: Int + periodLt: Int + periodLte: Int + periodStartTsEq: Time + periodStartTsGt: Time + periodStartTsGte: Time + periodStartTsLt: Time + periodStartTsLte: Time +} + +enum PeriodOrder { + period + period_start_ts +} + +type PerpLeaderboard { + avg_pct_pnl: Float! + input_margin: Float! + raw_pnl: Float! + raw_pnl_with_unrealized: Float! + trader_address: String! +} + +input PerpLeaderboardFilter { + trader_address: String +} + +enum PerpLeaderboardOrder { + avg_pct_pnl + raw_pnl + raw_pnl_with_unrealized + trader_address +} + type PerpMarket { base_reserve: Float! ecosystem_fund_fee_ratio: Float! @@ -101,7 +180,12 @@ enum PerpPositionOrder { } type Query { - communityPool(denom: String): [CommunityPoolToken!]! + communityPool( + limit: Int + order_by: CommunityPoolOrder + order_desc: Boolean + where: CommunityPoolFilter + ): [FloatToken!]! delegations( limit: Int order_by: DelegationOrder @@ -114,14 +198,26 @@ type Query { order_desc: Boolean where: DistributionCommissionFilter ): [DistributionCommission!]! - perpMarket(pair: String!): PerpMarket + markPriceCandles( + limit: Int + order_by: MarkPriceCandlesOrder + order_desc: Boolean + where: MarkPriceCandlesFilter + ): [MarkPriceCandle!]! + perpLeaderboard( + limit: Int + order_by: PerpLeaderboardOrder + order_desc: Boolean + where: PerpLeaderboardFilter + ): [PerpLeaderboard!]! + perpMarket(where: PerpMarketFilter): PerpMarket perpMarkets( limit: Int order_by: PerpMarketOrder order_desc: Boolean where: PerpMarketFilter ): [PerpMarket!]! - perpPosition(pair: String!, trader_address: String!): PerpPosition + perpPosition(where: PerpPositionFilter): PerpPosition perpPositions( limit: Int order_by: PerpPositionOrder @@ -170,6 +266,7 @@ type Query { order_desc: Boolean where: SpotPoolFilter ): [SpotPool!]! + stats: Stats! unbondings( limit: Int order_by: UnbondingOrder @@ -252,7 +349,7 @@ type SpotPoolCreated { block: Block! pool: SpotPool! pool_shares: SharesToken! - user_address: String! + user: User! } input SpotPoolCreatedFilter { @@ -269,7 +366,7 @@ type SpotPoolExited { block: Block! pool: SpotPool! pool_shares: SharesToken! - user_address: String! + user: User! } input SpotPoolExitedFilter { @@ -290,7 +387,7 @@ type SpotPoolJoined { block: Block! pool: SpotPool! pool_shares: SharesToken! - user_address: String! + user: User! } input SpotPoolJoinedFilter { @@ -312,7 +409,7 @@ type SpotPoolSwap { pool: SpotPool! token_in: Token! token_out: Token! - user_address: String! + user: User! } input SpotPoolSwapFilter { @@ -329,6 +426,223 @@ enum SpotPoolSwapOrder { user_address } +type Stats { + fees( + limit: Int + order: StatsFeesOrder + orderDesc: Boolean + where: PeriodFilter + ): [StatsFees!]! + perpOpenInterest( + limit: Int + order: StatsPerpOpenInterestOrder + orderDesc: Boolean + where: PeriodFilter + ): [StatsPerpOpenInterest!]! + perpPnl( + limit: Int + order: StatsPerpPnlOrder + orderDesc: Boolean + where: PeriodFilter + ): [StatsPerpPnl!]! + totals( + limit: Int + order: StatsTotalsOrder + orderDesc: Boolean + where: PeriodFilter + ): [StatsTotals!]! + tvl( + limit: Int + order: StatsTvlOrder + orderDesc: Boolean + where: PeriodFilter + ): [StatsTvl!]! + users( + limit: Int + order: StatsUsersOrder + orderDesc: Boolean + where: PeriodFilter + ): [StatsUsers!]! + volume( + limit: Int + order: StatsVolumeOrder + orderDesc: Boolean + where: PeriodFilter + ): [StatsVolume!]! +} + +type StatsFees { + feesLiquidations: Float! + feesLiquidationsCumulative: Float! + feesPerp: Float! + feesPerpCumulative: Float! + feesSwap: Float! + feesSwapCumulative: Float! + feesTotal: Float! + feesTotalCumulative: Float! + period: Int! + periodStartTs: Time! +} + +enum StatsFeesOrder { + fees_liquidations + fees_liquidations_cumulative + fees_perp + fees_perp_cumulative + fees_swap + fees_swap_cumulative + fees_total + fees_total_cumulative + period + period_start_ts +} + +type StatsPerpOpenInterest { + openInterestLong: Float! + openInterestShort: Float! + openInterestTotal: Float! + period: Int! + periodStartTs: Time! +} + +enum StatsPerpOpenInterestOrder { + open_interest_long + open_interest_short + open_interest_total + period + period_start_ts +} + +type StatsPerpPnl { + loss: Float! + lossCumulative: Float! + netPnl: Float! + netPnlCumulative: Float! + period: Int! + periodStartTs: Time! + profit: Float! + profitCumulative: Float! +} + +enum StatsPerpPnlOrder { + loss + loss_cumulative + net_pnl + net_pnl_cumulative + period + period_start_ts + profit + profit_cumulative +} + +type StatsTotals { + period: Int! + periodStartTs: Time! + totalFeesLiquidations: Float! + totalFeesPerp: Float! + totalOpenInterest: Float! + totalPerp: Float! + totalSwap: Float! + totalTvl: Float! +} + +enum StatsTotalsOrder { + period + period_start_ts + total_fees_liquidations + total_fees_perp + total_open_interest + total_perp + total_swap + total_tvl +} + +type StatsTvl { + period: Int! + periodStartTs: Time! + tvlPerp: Float! + tvlStablecoin: Float! + tvlStaking: Float! + tvlSwap: Float! + tvlTotal: Float! +} + +enum StatsTvlOrder { + period + period_start_ts + tvl_perp + tvl_stablecoin + tvl_staking + tvl_swap + tvl_total +} + +type StatsUsers { + newUsersLp: Int! + newUsersLpCumulative: Int! + newUsersPerp: Int! + newUsersPerpCumulative: Int! + newUsersSwap: Int! + newUsersSwapCumulative: Int! + newUsersTotal: Int! + newUsersTotalCumulative: Int! + period: Int! + periodStartTs: Time! + uniqueUsersLp: Int! + uniqueUsersPerp: Int! + uniqueUsersSwap: Int! + uniqueUsersTotal: Int! + userActionsLp: Int! + userActionsPerp: Int! + userActionsSwap: Int! + userActionsTotal: Int! +} + +enum StatsUsersOrder { + new_users_lp + new_users_lp_cumulative + new_users_perp + new_users_perp_cumulative + new_users_swap + new_users_swap_cumulative + new_users_total + new_users_total_cumulative + period + period_start_ts + unique_users_lp + unique_users_perp + unique_users_swap + unique_users_total + user_actions_lp + user_actions_perp + user_actions_swap + user_actions_total +} + +type StatsVolume { + period: Int! + periodStartTs: Time! + volumePerp: Float! + volumePerpCumulative: Float! + volumeSwap: Float! + volumeSwapCumulative: Float! + volumeTotal: Float! + volumeTotalCumulative: Float! +} + +enum StatsVolumeOrder { + period + period_start_ts + volume_perp + volume_perp_cumulative + volume_swap + volume_swap_cumulative + volume_total + volume_total_cumulative +} + +scalar Time + type Token { amount: Int! denom: String! diff --git a/packages/indexer-nibi/src/heart-monitor.test.ts b/packages/indexer-nibi/src/heart-monitor.test.ts index 2a7f5ddd..27c7fccf 100644 --- a/packages/indexer-nibi/src/heart-monitor.test.ts +++ b/packages/indexer-nibi/src/heart-monitor.test.ts @@ -112,8 +112,52 @@ test("distributionCommissions", async () => { } }) +test("markPriceCandles", async () => { + const resp = await heartMonitor.markPriceCandles({ + limit: 1, + }) + expect(resp).toHaveProperty("markPriceCandles") + + if (resp.markPriceCandles!.length > 0) { + const [markPriceCandle] = resp.markPriceCandles! + const fields = [ + "close", + "high", + "low", + "open", + "pair", + "period", + "periodStartTs", + ] + fields.forEach((field: string) => { + expect(markPriceCandle).toHaveProperty(field) + }) + } +}) + +test("perpLeaderboard", async () => { + const resp = await heartMonitor.perpLeaderboard({ + limit: 1, + }) + expect(resp).toHaveProperty("perpLeaderboard") + + if (resp.perpLeaderboard!.length > 0) { + const [perpLeaderboard] = resp.perpLeaderboard! + const fields = [ + "avg_pct_pnl", + "input_margin", + "raw_pnl", + "raw_pnl_with_unrealized", + "trader_address", + ] + fields.forEach((field: string) => { + expect(perpLeaderboard).toHaveProperty(field) + }) + } +}) + test("perpMarket", async () => { - const resp = await heartMonitor.perpMarket({ pair: "" }) + const resp = await heartMonitor.perpMarket({ where: { pair: "" } }) expect(resp).toHaveProperty("perpMarket") if (resp.perpMarket) { @@ -187,7 +231,9 @@ test("perpMarkets", async () => { }) test("perpPosition", async () => { - const resp = await heartMonitor.perpPosition({ pair: "", trader_address: "" }) + const resp = await heartMonitor.perpPosition({ + where: { pair: "", trader_address: "" }, + }) expect(resp).toHaveProperty("perpPosition") if (resp.perpPosition) { @@ -234,7 +280,6 @@ test("perpPositions", async () => { "bad_debt", "last_updated_block", ] - console.log(resp) fields.forEach((field: string) => { expect(perpPositions).toHaveProperty(field) }) @@ -364,6 +409,49 @@ test("spotPoolSwap", async () => { } }) +test("stats", async () => { + const resp = await heartMonitor.stats({ + totals: { + limit: 1, + }, + fees: { + limit: 1, + }, + perpOpenInterest: { + limit: 1, + }, + tvl: { + limit: 1, + }, + perpPnl: { + limit: 1, + }, + users: { + limit: 1, + }, + volume: { + limit: 1, + }, + }) + expect(resp).toHaveProperty("stats") + + if (resp.stats) { + const stats = resp.stats! + const fields = [ + "totals", + "fees", + "perpOpenInterest", + "tvl", + "perpPnl", + "users", + "volume", + ] + fields.forEach((field: string) => { + expect(stats).toHaveProperty(field) + }) + } +}) + test("unbondings", async () => { const resp = await heartMonitor.unbondings({ limit: 1, @@ -427,19 +515,6 @@ test("validators", async () => { } }) -// test("perpLeaderboard", async () => { -// const resp = await heartMonitor.perpLeaderboard() -// expect(resp).toHaveProperty("perpLeaderboard") - -// if (resp.perpLeaderboard!.length > 0) { -// const [config] = resp.perpLeaderboard! -// const fields = ["traderAddress", "percentagePnl", "rawPnl", "inputMargin"] -// fields.forEach((field: string) => { -// expect(config).toHaveProperty(field) -// }) -// } -// }) - describe("gql cleanResponse", () => { test("should return the response data if rawResp is ok and contains data", async () => { const rawResp = { diff --git a/packages/indexer-nibi/src/heart-monitor.ts b/packages/indexer-nibi/src/heart-monitor.ts index 5160198b..3e7cdf3b 100644 --- a/packages/indexer-nibi/src/heart-monitor.ts +++ b/packages/indexer-nibi/src/heart-monitor.ts @@ -3,6 +3,8 @@ import { QueryCommunityPoolArgs, QueryDelegationsArgs, QueryDistributionCommissionsArgs, + QueryMarkPriceCandlesArgs, + QueryPerpLeaderboardArgs, QueryPerpMarketArgs, QueryPerpMarketsArgs, QueryPerpPositionArgs, @@ -54,6 +56,12 @@ import { users, validators, } from "./query" +import { + GqlOutMarkPriceCandles, + markPriceCandles, +} from "./query/markPriceCandles" +import { GqlOutPerpLeaderboard, perpLeaderboard } from "./query/perpLeaderboard" +import { GqlOutStats, QueryStatsArgs, stats } from "./query/stats" /** IHeartMonitor is an interface for a Heart Monitor GraphQL API. * Each of its methods corresponds to a query function. */ @@ -70,6 +78,14 @@ export interface IHeartMonitor { args: QueryDistributionCommissionsArgs ) => Promise + readonly markPriceCandles: ( + args: QueryMarkPriceCandlesArgs + ) => Promise + + readonly perpLeaderboard: ( + args: QueryPerpLeaderboardArgs + ) => Promise + readonly perpMarket: (args: QueryPerpMarketArgs) => Promise readonly perpMarkets: ( @@ -110,6 +126,8 @@ export interface IHeartMonitor { args: QuerySpotPoolSwapArgs ) => Promise + readonly stats: (args: QueryStatsArgs) => Promise + readonly unbondings: (args: QueryUnbondingsArgs) => Promise readonly users: (args: QueryUsersArgs) => Promise @@ -147,6 +165,12 @@ export class HeartMonitor implements IHeartMonitor { distributionCommissions = async (args: QueryDistributionCommissionsArgs) => distributionCommissions(args, this.gqlEndpt) + markPriceCandles = async (args: QueryMarkPriceCandlesArgs) => + markPriceCandles(args, this.gqlEndpt) + + perpLeaderboard = async (args: QueryPerpLeaderboardArgs) => + perpLeaderboard(args, this.gqlEndpt) + perpMarket = async (args: QueryPerpMarketArgs) => perpMarket(args, this.gqlEndpt) @@ -179,6 +203,8 @@ export class HeartMonitor implements IHeartMonitor { spotPoolSwap = async (args: QuerySpotPoolSwapArgs) => spotPoolSwap(args, this.gqlEndpt) + stats = async (args: QueryStatsArgs) => stats(args, this.gqlEndpt) + unbondings = async (args: QueryUnbondingsArgs) => unbondings(args, this.gqlEndpt) diff --git a/packages/indexer-nibi/src/query/communityPool.ts b/packages/indexer-nibi/src/query/communityPool.ts index 07bd2e9b..67ae3716 100644 --- a/packages/indexer-nibi/src/query/communityPool.ts +++ b/packages/indexer-nibi/src/query/communityPool.ts @@ -1,12 +1,8 @@ import { defaultToken } from "../defaultObjects" import { convertObjectToPropertiesString, doGqlQuery, gqlQuery } from "../gql" -import { - QueryCommunityPoolArgs, - Query, - CommunityPoolToken, -} from "../gql/generated" +import { QueryCommunityPoolArgs, Query, FloatToken } from "../gql/generated" -export const defaultCommunityPoolObject: CommunityPoolToken = defaultToken +export const defaultCommunityPoolObject: FloatToken = defaultToken export interface GqlOutCommunityPool { communityPool?: Query["communityPool"] diff --git a/packages/indexer-nibi/src/query/markPriceCandles.ts b/packages/indexer-nibi/src/query/markPriceCandles.ts new file mode 100644 index 00000000..56114cb9 --- /dev/null +++ b/packages/indexer-nibi/src/query/markPriceCandles.ts @@ -0,0 +1,33 @@ +import { convertObjectToPropertiesString, doGqlQuery, gqlQuery } from "../gql" +import { + QueryMarkPriceCandlesArgs, + Query, + MarkPriceCandle, +} from "../gql/generated" + +export const defaultMarkPriceCandlesObject: MarkPriceCandle = { + close: 0, + high: 0, + low: 0, + open: 0, + pair: "", + period: 0, + periodStartTs: "", +} + +export interface GqlOutMarkPriceCandles { + markPriceCandles?: Query["markPriceCandles"] +} + +export const markPriceCandles = async ( + args: QueryMarkPriceCandlesArgs, + endpt: string +): Promise => + doGqlQuery( + gqlQuery( + "markPriceCandles", + args, + convertObjectToPropertiesString(defaultMarkPriceCandlesObject) + ), + endpt + ) diff --git a/packages/indexer-nibi/src/query/perpLeaderboard.ts b/packages/indexer-nibi/src/query/perpLeaderboard.ts new file mode 100644 index 00000000..1516a0cd --- /dev/null +++ b/packages/indexer-nibi/src/query/perpLeaderboard.ts @@ -0,0 +1,31 @@ +import { convertObjectToPropertiesString, doGqlQuery, gqlQuery } from "../gql" +import { + QueryPerpLeaderboardArgs, + Query, + PerpLeaderboard, +} from "../gql/generated" + +export const defaultPerpLeaderboardObject: PerpLeaderboard = { + avg_pct_pnl: 0, + input_margin: 0, + raw_pnl: 0, + raw_pnl_with_unrealized: 0, + trader_address: "", +} + +export interface GqlOutPerpLeaderboard { + perpLeaderboard?: Query["perpLeaderboard"] +} + +export const perpLeaderboard = async ( + args: QueryPerpLeaderboardArgs, + endpt: string +): Promise => + doGqlQuery( + gqlQuery( + "perpLeaderboard", + args, + convertObjectToPropertiesString(defaultPerpLeaderboardObject) + ), + endpt + ) diff --git a/packages/indexer-nibi/src/query/spotPoolSwap.ts b/packages/indexer-nibi/src/query/spotPoolSwap.ts index ecbf4ea2..5ca55978 100644 --- a/packages/indexer-nibi/src/query/spotPoolSwap.ts +++ b/packages/indexer-nibi/src/query/spotPoolSwap.ts @@ -1,4 +1,9 @@ -import { defaultBlock, defaultPool, defaultToken } from "../defaultObjects" +import { + defaultBlock, + defaultPool, + defaultToken, + defaultUser, +} from "../defaultObjects" import { convertObjectToPropertiesString, doGqlQuery, gqlQuery } from "../gql" import { Query, @@ -12,7 +17,7 @@ export const defaultSpotPoolSwapObject: SpotPoolSwap = { pool: defaultPool, token_in: defaultToken, token_out: defaultToken, - user_address: "", + user: defaultUser, } export interface GqlOutSpotPoolSwap { diff --git a/packages/indexer-nibi/src/query/stats.ts b/packages/indexer-nibi/src/query/stats.ts new file mode 100644 index 00000000..aa1c6f4f --- /dev/null +++ b/packages/indexer-nibi/src/query/stats.ts @@ -0,0 +1,177 @@ +import { convertObjectToPropertiesString, doGqlQuery, gqlQuery } from "../gql" +import { + Query, + StatsFeesArgs, + StatsFees, + StatsPerpOpenInterest, + StatsPerpPnl, + StatsTotals, + StatsTvl, + StatsUsers, + StatsVolume, + StatsPerpOpenInterestArgs, + StatsPerpPnlArgs, + StatsTotalsArgs, + StatsTvlArgs, + StatsUsersArgs, + StatsVolumeArgs, +} from "../gql/generated" + +export type QueryStatsArgs = { + fees: StatsFeesArgs + perpOpenInterest: StatsPerpOpenInterestArgs + perpPnl: StatsPerpPnlArgs + totals: StatsTotalsArgs + tvl: StatsTvlArgs + users: StatsUsersArgs + volume: StatsVolumeArgs +} + +export const defaultStatsFeesObject: StatsFees = { + feesLiquidations: 0, + feesLiquidationsCumulative: 0, + feesPerp: 0, + feesPerpCumulative: 0, + feesSwap: 0, + feesSwapCumulative: 0, + feesTotal: 0, + feesTotalCumulative: 0, + period: 0, + periodStartTs: "", +} +export const defaultPerpOpenInterestObject: StatsPerpOpenInterest = { + openInterestLong: 0, + openInterestShort: 0, + openInterestTotal: 0, + period: 0, + periodStartTs: "", +} + +export const defaultPerpPnlObject: StatsPerpPnl = { + loss: 0, + lossCumulative: 0, + netPnl: 0, + netPnlCumulative: 0, + period: 0, + periodStartTs: "", + profit: 0, + profitCumulative: 0, +} + +export const defaultTotalsObject: StatsTotals = { + period: 0, + periodStartTs: 0, + totalPerp: 0, + totalFeesPerp: 0, + totalFeesLiquidations: 0, + totalOpenInterest: 0, + totalSwap: 0, + totalTvl: 0, +} + +export const defaultTvlObject: StatsTvl = { + period: 0, + periodStartTs: "", + tvlPerp: 0, + tvlStablecoin: 0, + tvlStaking: 0, + tvlSwap: 0, + tvlTotal: 0, +} + +export const defaultUsersObject: StatsUsers = { + newUsersLp: 0, + newUsersLpCumulative: 0, + newUsersPerp: 0, + newUsersPerpCumulative: 0, + newUsersSwap: 0, + newUsersSwapCumulative: 0, + newUsersTotal: 0, + newUsersTotalCumulative: 0, + period: 0, + periodStartTs: "", + userActionsPerp: 0, + uniqueUsersLp: 0, + uniqueUsersPerp: 0, + uniqueUsersSwap: 0, + uniqueUsersTotal: 0, + userActionsLp: 0, + userActionsSwap: 0, + userActionsTotal: 0, +} + +export const defaultVolumeObject: StatsVolume = { + volumePerp: 0, + volumePerpCumulative: 0, + volumeSwap: 0, + volumeSwapCumulative: 0, + volumeTotal: 0, + volumeTotalCumulative: 0, + period: 0, + periodStartTs: "", +} + +export interface GqlOutStats { + stats?: Query["stats"] +} + +export const stats = async ( + args: QueryStatsArgs, + endpt: string +): Promise => { + const statsQuery = [ + gqlQuery( + "fees", + args.fees, + convertObjectToPropertiesString(defaultStatsFeesObject), + true + ), + gqlQuery( + "perpOpenInterest", + args.perpOpenInterest, + convertObjectToPropertiesString(defaultPerpOpenInterestObject), + true + ), + gqlQuery( + "perpPnl", + args.perpPnl, + convertObjectToPropertiesString(defaultPerpPnlObject), + true + ), + gqlQuery( + "totals", + args.totals, + convertObjectToPropertiesString(defaultTotalsObject), + true + ), + gqlQuery( + "tvl", + args.tvl, + convertObjectToPropertiesString(defaultTvlObject), + true + ), + gqlQuery( + "users", + args.users, + convertObjectToPropertiesString(defaultUsersObject), + true + ), + gqlQuery( + "volume", + args.volume, + convertObjectToPropertiesString(defaultVolumeObject), + true + ), + ] + + console.log(statsQuery) + + return doGqlQuery( + `{ + stats { + ${statsQuery.join("\n")} + } + }`, + endpt + ) +} diff --git a/packages/nibijs/docs/classes/StableSwap.md b/packages/nibijs/docs/classes/StableSwap.md index 223978ad..7e894b6e 100644 --- a/packages/nibijs/docs/classes/StableSwap.md +++ b/packages/nibijs/docs/classes/StableSwap.md @@ -178,7 +178,7 @@ y() Calculate x[j] if one makes x[i] = x Done by solving quadratic equation iteratively. -x*1**2 + x1 * (sum' - (A*n**n - 1) * D / (A _ n**n)) = D ** (n+1)/(n \*\* (2 _ n) \_ prod' \* A) +x*1\*\*2 + x1 * (sum' - (A*n\*\*n - 1) * D / (A _ n**n)) = D ** (n+1)/(n \*\* (2 _ n) \_ prod' \* A) x_1\*\*2 + b\*x_1 = c x_1 = (x_1\**2 + c) / (2*x_1 + b)