From c591541b50f50d21ebe10146f0d250264e33d348 Mon Sep 17 00:00:00 2001 From: rabi-siddique Date: Thu, 19 Dec 2024 14:21:14 +0500 Subject: [PATCH] ci: validate vault and reserve metrics data --- .../vaults-and-reserve-metrics-testing.yml | 100 ++++++++ scripts/queries.mjs | 223 ++++++++++++++++++ scripts/validateData.mjs | 42 ++++ src/test/mappingHandlers.test.ts | 151 ------------ 4 files changed, 365 insertions(+), 151 deletions(-) create mode 100644 .github/workflows/vaults-and-reserve-metrics-testing.yml create mode 100644 scripts/queries.mjs create mode 100755 scripts/validateData.mjs diff --git a/.github/workflows/vaults-and-reserve-metrics-testing.yml b/.github/workflows/vaults-and-reserve-metrics-testing.yml new file mode 100644 index 00000000..968c07af --- /dev/null +++ b/.github/workflows/vaults-and-reserve-metrics-testing.yml @@ -0,0 +1,100 @@ +name: Vaults and Reserve Indexing +on: + pull_request: + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Start A3P container + run: docker compose --profile ci up -d a3p + + - run: corepack enable + shell: bash + + - name: Setup Node.js environment + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: yarn + + - name: Install dependencies + run: yarn install + + - name: Start subql indexer + env: + AGORIC_NET: ci + run: yarn dev + + - name: Print initial logs of all containers + run: | + echo "Fetching initial logs for all containers..." + containers=$(docker ps --format '{{.ID}}') + for container in $containers; do + echo "Fetching initial logs for container $container..." + docker logs $container + done + + - name: Set Execute Permission for All Scripts + run: chmod +x ./scripts/*.mjs + + - name: Wait for GraphQL server + run: sleep 60 + + - name: Test Vaults + run: ./scripts/validateData.mjs + env: + entity: vaults + blockHeight: 742 + apiUrl: 'http://localhost:3000/' + + - name: Test VaultStatesDailies + run: ./scripts/validateData.mjs + env: + entity: vaultStatesDailies + blockHeight: 742 + apiUrl: 'http://localhost:3000/' + + - name: Test VaultManagerGovernance + run: ./scripts/validateData.mjs + env: + entity: vaultManagerGovernances + blockHeight: 1212 + apiUrl: 'http://localhost:3000/' + + - name: Test VaultManagerMetrics + run: ./scripts/validateData.mjs + env: + entity: vaultManagerMetrics + blockHeight: 1212 + apiUrl: 'http://localhost:3000/' + + - name: Test VaultManagerMetricsDaily + run: ./scripts/validateData.mjs + env: + entity: vaultManagerMetricsDailies + blockHeight: 1212 + apiUrl: 'http://localhost:3000/' + + - name: Test ReserveMetrics + run: ./scripts/validateData.mjs + env: + entity: reserveMetrics + blockHeight: 1212 + apiUrl: 'http://localhost:3000/' + + - name: Test ReserveAllocationMetrics + run: ./scripts/validateData.mjs + env: + entity: reserveAllocationMetrics + blockHeight: 1212 + apiUrl: 'http://localhost:3000/' + + - name: Test ReserveAllocationMetricsDaily + run: ./scripts/validateData.mjs + env: + entity: reserveAllocationMetricsDailies + blockHeight: 1212 + apiUrl: 'http://localhost:3000/' diff --git a/scripts/queries.mjs b/scripts/queries.mjs new file mode 100644 index 00000000..92d508ae --- /dev/null +++ b/scripts/queries.mjs @@ -0,0 +1,223 @@ +const buildFilter = (filters) => { + const filterStrings = Object.entries(filters).map(([key, value]) => { + return `${key}: {equalTo: "${value}"}`; + }); + return `(filter: {${filterStrings.join(', ')}})`; +}; + +export const getQuery = (entity, filters) => { + const filterString = buildFilter(filters); + + const queries = { + vaults: `query { + vaults ${filterString} { + nodes { + balance + lockedValue + coin + denom + debt + state + } + } + }`, + vaultStatesDailies: `query { + vaultStatesDailies ${filterString} { + nodes { + active + closed + liquidating + liquidated + } + } + }`, + vaultManagerGovernances: `query { + vaultManagerGovernances ${filterString} { + nodes { + id + debtLimit + interestRateDenominator + interestRateNumerator + liquidationMarginDenominator + liquidationMarginNumerator + liquidationPaddingDenominator + liquidationPaddingNumerator + liquidationPenaltyDenominator + liquidationPenaltyNumerator + mintFeeDenominator + mintFeeNumerator + } + } + }`, + vaultManagerMetrics: `query { + vaultManagerMetrics ${filterString} { + nodes { + id + liquidatingCollateralBrand + liquidatingCollateralValue + liquidatingDebtBrand + liquidatingDebtValue + lockedQuoteDenominator + lockedQuoteNumerator + numActiveVaults + numLiquidatingVaults + numLiquidationsAborted + numLiquidationsCompleted + retainedCollateral + totalCollateral + totalCollateralSold + totalDebt + totalOverageReceived + totalProceedsReceived + totalShortfallReceived + } + } + }`, + vaultManagerMetricsDailies: `query { + vaultManagerMetricsDailies ${filterString} { + nodes { + path + liquidatingCollateralBrand + liquidatingDebtBrand + liquidatingCollateralValueLast + liquidatingDebtValueLast + lockedQuoteDenominatorLast + lockedQuoteNumeratorLast + numActiveVaultsLast + numLiquidatingVaultsLast + numLiquidationsAbortedLast + numLiquidationsCompletedLast + retainedCollateralLast + totalCollateralLast + totalCollateralSoldLast + totalDebtLast + totalOverageReceivedLast + totalProceedsReceivedLast + totalShortfallReceivedLast + metricsCount + } + } + }`, + reserveMetrics: `query { + reserveMetrics ${filterString} { + nodes { + id + shortfallBalance + totalFeeBurned + totalFeeMinted + } + } + }`, + reserveAllocationMetrics: `query { + reserveAllocationMetrics ${filterString} { + nodes { + id + denom + key + value + } + } + }`, + reserveAllocationMetricsDailies: `query { + reserveAllocationMetricsDailies ${filterString} { + nodes { + denom + key + valueLast + metricsCount + } + } + }`, + }; + + return queries[entity]; +}; + +export const expectations = { + vaults: { + balance: 788000000, + lockedValue: 788000000, + coin: 'ATOM', + denom: 'ATOM', + debt: 4745610000, + state: 'active', + }, + vaultStatesDailies: { + active: 1, + closed: 0, + liquidating: 0, + liquidated: 0, + }, + vaultManagerGovernances: { + id: 'published.vaultFactory.managers.manager1.governance', + debtLimit: '1000000000', + interestRateDenominator: '100', + interestRateNumerator: '1', + liquidationMarginDenominator: '100', + liquidationMarginNumerator: '150', + liquidationPaddingDenominator: '100', + liquidationPaddingNumerator: '25', + liquidationPenaltyDenominator: '100', + liquidationPenaltyNumerator: '1', + mintFeeDenominator: '10000', + mintFeeNumerator: '50', + }, + vaultManagerMetrics: { + liquidatingCollateralBrand: 'stATOM', + liquidatingCollateralValue: '0', + liquidatingDebtBrand: 'IST', + liquidatingDebtValue: '0', + lockedQuoteDenominator: '0', + lockedQuoteNumerator: '0', + numActiveVaults: '0', + numLiquidatingVaults: '0', + numLiquidationsAborted: '0', + numLiquidationsCompleted: '0', + retainedCollateral: '0', + totalCollateral: '0', + totalCollateralSold: '0', + totalDebt: '0', + totalOverageReceived: '0', + totalProceedsReceived: '0', + totalShortfallReceived: '0', + }, + vaultManagerMetricsDailies: { + path: 'published.vaultFactory.managers.manager1.metrics', + liquidatingCollateralBrand: 'stATOM', + liquidatingDebtBrand: 'IST', + liquidatingCollateralValueLast: '0', + liquidatingDebtValueLast: '0', + lockedQuoteDenominatorLast: '0', + lockedQuoteNumeratorLast: '0', + numActiveVaultsLast: '0', + numLiquidatingVaultsLast: '0', + numLiquidationsAbortedLast: '0', + numLiquidationsCompletedLast: '0', + retainedCollateralLast: '0', + totalCollateralLast: '0', + totalCollateralSoldLast: '0', + totalDebtLast: '0', + totalOverageReceivedLast: '0', + totalProceedsReceivedLast: '0', + totalShortfallReceivedLast: '0', + metricsCount: '1', + }, + reserveMetrics: { + id: 'published.reserve.metrics', + shortfallBalance: '0', + totalFeeBurned: '0', + totalFeeMinted: '0', + }, + reserveAllocationMetrics: { + id: 'IST', + denom: 'IST', + key: 'Fee', + value: '187909157', + }, + reserveAllocationMetricsDailies: { + denom: 'IST', + key: 'Fee', + valueLast: '187909157', + metricsCount: '1', + }, +}; diff --git a/scripts/validateData.mjs b/scripts/validateData.mjs new file mode 100755 index 00000000..fb11ed8b --- /dev/null +++ b/scripts/validateData.mjs @@ -0,0 +1,42 @@ +#! /usr/bin/env node +/* eslint-env node */ +import './lockdown.mjs'; +import { equal } from 'node:assert/strict'; +import { getQuery, expectations } from './queries.mjs'; +import { assertAllDefined } from '@agoric/internal'; + +const apiUrl = process.env.apiUrl || 'https://api.subquery.network/sq/agoric-labs/agoric-mainnet-v2'; +console.log(`API URL set to: ${apiUrl}`); + +const { entity, blockHeight } = process.env; +console.log(`Entity: ${entity}, Block Height: ${blockHeight}`); + +assertAllDefined({ entity, blockHeight }); + +const filter = + entity === 'vaultManagerMetricsDailies' || entity === 'reserveAllocationMetricsDailies' + ? { blockHeightLast: blockHeight } + : { blockHeight }; + +try { + const graphqlQuery = { query: getQuery(entity, filter) }; + + const response = await fetch(apiUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify(graphqlQuery), + }); + + const jsonResponse = await response.json(); + const nodes = jsonResponse?.data[entity]?.nodes; + console.log('Node:', nodes); + + for (const key of Object.keys(expectations)) { + equal(nodes[0][key], expectations[entity][key]); + } +} catch (error) { + console.error('Error:', error); +} diff --git a/src/test/mappingHandlers.test.ts b/src/test/mappingHandlers.test.ts index c9b68d7d..771332c9 100644 --- a/src/test/mappingHandlers.test.ts +++ b/src/test/mappingHandlers.test.ts @@ -7,15 +7,7 @@ import { PsmGovernance, PsmMetrics, PsmMetricsDaily, - ReserveAllocationMetrics, - ReserveAllocationMetricsDaily, - ReserveMetrics, StateChangeEvent, - Vault, - VaultManagerGovernance, - VaultManagerMetrics, - VaultManagerMetricsDaily, - VaultStatesDaily, Wallet, } from '../types'; @@ -46,149 +38,6 @@ subqlTest( 'handleStateChangeEvent', ); -const vault = new Vault( - 'published.vaultFactory.managers.manager0.vaults.vault6', - BigInt(742), - new Date('2024-12-09 23:13:19.186'), - 'published.wallet.agoric1ee9hr0jyrxhy999y755mp862ljgycmwyp4pl7q.current', -); - -vault.balance = BigInt(788000000); -vault.lockedValue = BigInt(788000000); -vault.coin = 'ATOM'; -vault.denom = 'ATOM'; -vault.debt = BigInt(4745610000); -vault.state = 'active'; - -subqlTest( - 'Vault and VaultStateDailies at height 742', - 742, - [], - [ - vault, - new VaultStatesDaily( - '20241209', - BigInt(742), - new Date('2024-12-09 23:13:19.186'), - BigInt(1), - BigInt(0), - BigInt(0), - BigInt(0), - BigInt(0), - ), - ], - - 'handleStateChangeEvent', -); - -const reserveAllocationMetricsDaily = new ReserveAllocationMetricsDaily( - 'IST:20241216', - 'IST', - 20241216, - BigInt(1212), - new Date('2024-12-16T11:42:27.000Z'), -); - -reserveAllocationMetricsDaily.denom = 'IST'; -reserveAllocationMetricsDaily.key = 'Fee'; -reserveAllocationMetricsDaily.valueLast = BigInt(184980868); -reserveAllocationMetricsDaily.metricsCount = BigInt(1); - -const vaultManagerMetricsDaily = new VaultManagerMetricsDaily( - 'published.vaultFactory.managers.manager1.metrics:20241216', - 'published.vaultFactory.managers.manager1.metrics', - 20241216, - BigInt(1212), - new Date('2024-12-16 11:42:27.202'), -); - -vaultManagerMetricsDaily.liquidatingCollateralBrand = 'stATOM'; -vaultManagerMetricsDaily.liquidatingDebtBrand = 'IST'; -vaultManagerMetricsDaily.liquidatingCollateralValueLast = BigInt(0); -vaultManagerMetricsDaily.liquidatingDebtValueLast = BigInt(0); -vaultManagerMetricsDaily.lockedQuoteDenominatorLast = BigInt(0); -vaultManagerMetricsDaily.lockedQuoteNumeratorLast = BigInt(0); -vaultManagerMetricsDaily.numActiveVaultsLast = BigInt(0); -vaultManagerMetricsDaily.numLiquidatingVaultsLast = BigInt(0); -vaultManagerMetricsDaily.numLiquidationsAbortedLast = BigInt(0); -vaultManagerMetricsDaily.numLiquidationsCompletedLast = BigInt(0); -vaultManagerMetricsDaily.retainedCollateralLast = BigInt(0); -vaultManagerMetricsDaily.totalCollateralLast = BigInt(0); -vaultManagerMetricsDaily.totalCollateralSoldLast = BigInt(0); -vaultManagerMetricsDaily.totalDebtLast = BigInt(0); -vaultManagerMetricsDaily.totalOverageReceivedLast = BigInt(0); -vaultManagerMetricsDaily.totalProceedsReceivedLast = BigInt(0); -vaultManagerMetricsDaily.totalShortfallReceivedLast = BigInt(0); -vaultManagerMetricsDaily.metricsCount = BigInt(1); - -// DISABLED because the timestamp for these entities is changed on each run of the a3p container -// subqlTest( -// 'VaultManagerGovernance, VaultManagerMetrics, VaultManagerMetricsDaily, ReserveMetrics, \ -// ReserveAllocationMetrics, and ReserveAllocationMetricsDaily at block height 1212', -// 1212, -// [], -// [ -// new VaultManagerGovernance( -// 'published.vaultFactory.managers.manager1.governance', -// BigInt(1212), -// new Date('2024-12-16 11:42:27.202'), -// BigInt(1000000000), -// BigInt(100), -// BigInt(1), -// BigInt(100), -// BigInt(150), -// BigInt(100), -// BigInt(25), -// BigInt(100), -// BigInt(1), -// BigInt(10000), -// BigInt(50), -// ), -// new VaultManagerMetrics( -// 'published.vaultFactory.managers.manager1.metrics', -// BigInt(1212), -// new Date('2024-12-16 11:42:27.202'), -// 'stATOM', -// BigInt(0), -// 'IST', -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// ), -// vaultManagerMetricsDaily, -// new ReserveMetrics( -// 'published.reserve.metrics', -// BigInt(1212), -// new Date('2024-12-16T11:42:27.202Z'), -// BigInt(0), -// BigInt(0), -// BigInt(0), -// ), -// new ReserveAllocationMetrics( -// 'IST', -// BigInt(1212), -// new Date('2024-12-16T11:42:27.202Z'), -// 'IST', -// 'Fee', -// BigInt(184980868), -// 'published.reserve.metrics', -// ), -// reserveAllocationMetricsDaily, -// ], -// 'handleStateChangeEvent', -// ); - subqlTest( 'BoardAux at block 643', 643,