Skip to content

Commit

Permalink
feat(introspection): v21 (#188)
Browse files Browse the repository at this point in the history
* feat(introspection): v21

* feat(v21 sdk): sDK

* fix(fix): tests

* fix(fix): generic func

* fix(build): build
  • Loading branch information
cgilbe27 authored Jul 26, 2023
1 parent b6a9410 commit 0ef590c
Show file tree
Hide file tree
Showing 89 changed files with 4,320 additions and 2,545 deletions.
1 change: 0 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ const common = {
],
"no-use-before-define": "off",
"no-useless-constructor": "off",
"prettier/prettier": "error",
quotes: ["off"],
"quote-props": ["warn", "as-needed"],
radix: "off",
Expand Down
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@

# Primary maintainers

* @Unique-Divine @k-yang @cgilbe27 @elshenak
- @Unique-Divine @k-yang @cgilbe27 @elshenak
4 changes: 4 additions & 0 deletions packages/indexer-nibi/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline

- .

## v0.21.6

- V21 introspection

## v0.21.4

- Actually fix build
Expand Down
12 changes: 8 additions & 4 deletions packages/indexer-nibi/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@nibiruchain/indexer-nibi",
"description": "GraphQL API client for the Nibiru Chain indexer (heart-monitor)",
"version": "0.21.4",
"version": "0.21.6",
"license": "MIT",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand All @@ -11,17 +11,21 @@
"scripts": {
"build": "tsc --build",
"build:watch": "tsc --build --watch",
"gql-generate": "rm -rf gql && graphql-code-generator --config ./src/graphql-codegen/codegen.ts",
"clean": "tsc --clean",
"test": "jest",
"test:watch": "jest --watch",
"coverage": "jest --coverage"
},
"dependencies": {
"cross-fetch": "^3.1.5"
},
"devDependencies": {
"@babel/core": "7.22.9",
"@graphql-codegen/cli": "^4.0.1",
"@graphql-codegen/client-preset": "^4.0.1",
"@graphql-codegen/typescript": "^4.0.1",
"@types/jest": "^29.1.2",
"@types/node-fetch": "^2.6.2",
"cross-fetch": "4.0.0",
"graphql": "^16.7.1",
"jest": "^28.1.3",
"ts-jest": "^28.0.0-next.3"
},
Expand Down
112 changes: 112 additions & 0 deletions packages/indexer-nibi/src/defaultObjects.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { ValidatorStatus } from "./gql/generated"

export const defaultToken = {
denom: "",
amount: 0,
}

export const defaultTokenAsString = {
denom: "",
amount: "",
}

export const defaultBlock = {
block: 0,
block_duration: 0,
block_ts: 0,
num_txs: 0,
}

export const defaultValidator = {
commission_update_time: "",
commission_rates: {
max_change_rate: 0,
max_rate: 0,
rate: 0,
},
delegator_shares: 0,
description: {
details: "",
identity: "",
moniker: "",
security_contact: "",
website: "",
},
jailed: false,
operator_address: "",
min_self_delegation: 0,
status: ValidatorStatus.Bonded,
tokens: 0,
unbonding_block: defaultBlock,
unbonding_time: "",
}

export const defaultActor = {
address: "",
balances: [defaultToken],
created_block: defaultBlock,
}

export const defaultDelegator = defaultActor

export const defaultUser = defaultActor

export const defaultPerpMarket = {
base_reserve: 0,
ecosystem_fund_fee_ratio: 0,
enabled: true,
exchange_fee_ratio: 0,
funding_rate_epoch_id: "",
index_price_twap: 0,
is_deleted: false,
latest_cumulative_premium_fraction: 0,
liquidation_fee_ratio: 0,
maintenance_margin_ratio: 0,
mark_price: 0,
mark_price_twap: 0,
max_leverage: 0,
pair: "",
partial_liquidation_ratio: 0,
prepaid_bad_debt: defaultToken,
price_multiplier: 0,
quote_reserve: 0,
sqrt_depth: 0,
total_long: 0,
total_short: 0,
twap_lookback_window: "",
}

export const defaultPerpPosition = {
bad_debt: 0,
last_updated_block: defaultBlock,
latest_cumulative_premium_fraction: 0,
margin: 0,
margin_ratio: 0,
open_notional: 0,
pair: "",
position_notional: 0,
size: 0,
trader_address: "",
unrealized_funding_payment: 0,
unrealized_pnl: 0,
}

export const defaultPool = {
amplification: 0,
created_block: defaultBlock,
exit_fee: 0,
swap_fee: 0,
pool_id: 0,
tokens: [defaultToken],
pool_type: "",
total_shares: defaultTokenAsString,
total_weight: 0,
weights: [defaultToken],
}

export const defaultSpotPool = {
block: defaultBlock,
pool: defaultPool,
pool_shares: defaultTokenAsString,
user_address: "",
}
145 changes: 101 additions & 44 deletions packages/indexer-nibi/src/gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,63 +8,120 @@ declare global {

window.fetch = cf.fetch

/**
* The workhorse function that fetches data from the GraphQL endpoint.
*
* ### Args:
* @param {string} gqlQuery - raw GraphQL query string
* @param {string} gqlEndpt - URL for the GraphQL endpoint.
* @returns {Promise<any>}
*/
export async function doGqlQuery(
gqlQuery: string,
gqlEndpt: string
): Promise<any> {
const encodedGqlQuery = encodeURI(gqlQuery)
const fetchString = `${gqlEndpt}?query=${encodedGqlQuery}`
const rawResp = await window.fetch(fetchString)
return cleanResponse(rawResp)
const createGqlEndpt = (chain: string) =>
`https://hm-graphql.${chain}.nibiru.fi/graphql`

export const arg = (name: string, value: any, ignoreQuotes?: boolean) => {
const isString = typeof value === "string" && !ignoreQuotes ? `"` : ""

return `${name}: ${isString}${value}${isString}`
}

export const getWhereArgArr = (whereArgs: any) =>
`where: {
${Object.keys(whereArgs)
.map((key) => arg(key, whereArgs[key]))
.join(", ")}
}`

export const convertObjectToPropertiesString = (obj: any) => {
let result = ""

for (const key in obj) {
const value = obj[key]
if (Array.isArray(value)) {
const innerString = value
.map(
(item) =>
`${key} {
${Object.keys(item)
.map((k) => `${k}`)
.join("\n")}
}`
)
.join("\n")
result += `${innerString}\n`
} else if (typeof value === "object" && value !== null) {
result += `${key} {
${convertObjectToPropertiesString(value)}
}\n`
} else {
result += `${key}\n`
}
}

return result
}

export async function cleanResponse(rawResp: Response): Promise<any> {
const respJson: any = await rawResp.json().catch((err) => {
export const cleanResponse = async (rawResp: Response) => {
const respJson = await rawResp.json().catch((err) => {
console.error(err)
})
// console.debug("DEBUG respJson: %o", respJson)

if (!rawResp.ok || respJson === undefined) {
if (!rawResp.ok || !respJson) {
throw new Error(`${respJson}`)
} else if (respJson.data !== undefined) {
} else if (respJson.data) {
return respJson.data
} else {
return respJson
}
}

/**
* arg: Returns the string format for an "argument" in a GraphQL query.
*
* @param {string} name - name of the argument
* @param {*} value - value of the argument
* @returns {string}
*/
export const arg = (name: string, value: any): string => `${name}: ${value}`

/** createGqlEndpt: Returns the URL of a heart monitor endpoint based on the
* standard 'chainNickname' included as part of the Tendermint RPC endpoint and
* LCD/Rest endpoint.
*
* Example: The chain ID "nibiru-testnet-2" has the chain nickname, "testnet",
* and chain number, "2". The combination of the nickname and number is what
* we'd use as prefix in the hm-graphql URL.
*/
const createGqlEndpt = (chain: string): string =>
`https://hm-graphql.${chain}.nibiru.fi/graphql`
export const gqlQuery = <T>(
name: string,
typedQueryArgs: { [key: string]: T },
properties: string
) => {
let queryArgList = []

if (
typedQueryArgs.where !== undefined ||
typedQueryArgs.limit !== undefined ||
typedQueryArgs.order_by !== undefined ||
typedQueryArgs.order_desc !== undefined
) {
if (typedQueryArgs.where !== undefined) {
queryArgList.push(getWhereArgArr(typedQueryArgs.where))
}

if (typedQueryArgs.limit !== undefined) {
queryArgList.push(arg("limit", typedQueryArgs.limit))
}

if (typedQueryArgs.order_by !== undefined) {
queryArgList.push(arg("order_by", typedQueryArgs.order_by, true))
}

if (typedQueryArgs.order_desc !== undefined) {
queryArgList.push(arg("order_desc", typedQueryArgs.order_desc))
}
} else {
queryArgList = Object.keys(typedQueryArgs).map((key) =>
arg(key, typedQueryArgs[key])
)
}

const hasQueryList = (char: string) => (queryArgList.length > 0 ? char : "")

return `{
${name} ${hasQueryList("(")}${queryArgList.join(", ")}${hasQueryList(")")} {
${properties}
}
}`
}

export const doGqlQuery = async (gqlQuery: string, gqlEndpt: string) => {
const encodedGqlQuery = encodeURI(gqlQuery)
const fetchString = `${gqlEndpt}?query=${encodedGqlQuery}`
const rawResp = await window.fetch(fetchString)
return cleanResponse(rawResp)
}

export function gqlEndptFromTmRpc(endptTm: string): string | null {
const endptTmParts: string[] = endptTm.split(".")
export const gqlEndptFromTmRpc = (endptTm: string) => {
const endptTmParts = endptTm.split(".")
// rpcIdx: the index of the substring that includes rpc
let rpcIdx: number = -1
let rpcIdx = -1
endptTmParts.forEach((part, idx) => {
if (part.includes("rpc")) {
rpcIdx = idx
Expand All @@ -73,8 +130,8 @@ export function gqlEndptFromTmRpc(endptTm: string): string | null {

// nicknameIdx: the index of the substring that includes the chain nickname
const nicknameIdx = rpcIdx + 1
const invalidRpcIdx: boolean = rpcIdx === -1
const invalidNicknameIdx: boolean = nicknameIdx === endptTmParts.length
const invalidRpcIdx = rpcIdx === -1
const invalidNicknameIdx = nicknameIdx === endptTmParts.length
if (invalidRpcIdx || invalidNicknameIdx) {
return null
}
Expand Down
Loading

0 comments on commit 0ef590c

Please sign in to comment.