diff --git a/.github/workflows/liquidation.yml b/.github/workflows/liquidation.yml index 54cb9d4c..f062deeb 100644 --- a/.github/workflows/liquidation.yml +++ b/.github/workflows/liquidation.yml @@ -37,9 +37,6 @@ jobs: docker logs $container done - - name: Set Execute Permission for All Scripts - run: chmod +x ./scripts/*.mjs - - name: Set ATOM Price to 12.34 run: ./scripts/changePrice.mjs env: @@ -50,7 +47,6 @@ jobs: - name: Get active vaults run: ./scripts/getActiveVaults.mjs env: - apiUrl: 'http://localhost:3000/' expectedVaults: 7 - name: Create Vault with 100 Minted and 15 Collateral @@ -86,7 +82,6 @@ jobs: - name: Get active vaults run: ./scripts/getActiveVaults.mjs env: - apiUrl: 'http://localhost:3000/' expectedVaults: 10 - name: Place bid for 90IST @@ -128,11 +123,8 @@ jobs: - name: Check liquidation indexing run: ./scripts/checkLiquidation.mjs - env: - apiUrl: 'http://localhost:3000/' - name: Get active vaults run: ./scripts/getActiveVaults.mjs env: - apiUrl: 'http://localhost:3000/' expectedVaults: 7 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..cff8e6c5 --- /dev/null +++ b/.github/workflows/vaults-and-reserve-metrics-testing.yml @@ -0,0 +1,79 @@ +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 + + # We tried delays of 10, 20, and 30 seconds, but a 60-second delay is the most efficient + # and ensures that the server is fully ready, without causing any issues. + - name: Wait for GraphQL server + run: sleep 60 + + - name: Test VaultManagerGovernance + run: ./scripts/validateData.mjs + env: + entity: vaultManagerGovernances + blockHeight: 1212 + + - name: Test VaultManagerMetrics + run: ./scripts/validateData.mjs + env: + entity: vaultManagerMetrics + blockHeight: 1212 + + - name: Test VaultManagerMetricsDaily + run: ./scripts/validateData.mjs + env: + entity: vaultManagerMetricsDailies + blockHeight: 1212 + + - name: Test ReserveMetrics + run: ./scripts/validateData.mjs + env: + entity: reserveMetrics + blockHeight: 1212 + + - name: Test ReserveAllocationMetrics + run: ./scripts/validateData.mjs + env: + entity: reserveAllocationMetrics + blockHeight: 1212 + + - name: Test ReserveAllocationMetricsDaily + run: ./scripts/validateData.mjs + env: + entity: reserveAllocationMetricsDailies + blockHeight: 1212 diff --git a/scripts/changePrice.mjs b/scripts/changePrice.mjs index 45fbaa7f..95b0c7f2 100755 --- a/scripts/changePrice.mjs +++ b/scripts/changePrice.mjs @@ -20,4 +20,5 @@ try { console.log('Standard output:', stdout); } catch (error) { console.error('Error:', error); + process.exit(1); } diff --git a/scripts/checkLiquidation.mjs b/scripts/checkLiquidation.mjs old mode 100644 new mode 100755 index 008f9ca6..82d04a32 --- a/scripts/checkLiquidation.mjs +++ b/scripts/checkLiquidation.mjs @@ -93,7 +93,7 @@ const validate = async ({ apiUrl, maxRetries, retryDuration, expectations, filte process.exit(1); }; -const apiUrl = process.env.API_URL || 'http://localhost:3000/'; +const apiUrl = 'http://localhost:3000/'; console.log(`API URL set to: ${apiUrl}`); try { @@ -118,4 +118,5 @@ try { console.log('Validation successful for liquidated vaults.'); } catch (error) { console.error('Validation failed:', error); + process.exit(1); } diff --git a/scripts/createVault.mjs b/scripts/createVault.mjs old mode 100644 new mode 100755 diff --git a/scripts/getActiveVaults.mjs b/scripts/getActiveVaults.mjs old mode 100644 new mode 100755 index 4d4cb21c..70d23af6 --- a/scripts/getActiveVaults.mjs +++ b/scripts/getActiveVaults.mjs @@ -50,7 +50,6 @@ const getActiveVaults = async (apiUrl, expectedVaults) => { process.exit(1); }; -const apiUrl = process.env.apiUrl; const expectedVaults = parseInt(process.env.expectedVaults, 10); - +const apiUrl = 'http://localhost:3000/'; getActiveVaults(apiUrl, expectedVaults); diff --git a/scripts/lockdown.mjs b/scripts/lockdown.mjs old mode 100644 new mode 100755 diff --git a/scripts/placeBid.mjs b/scripts/placeBid.mjs old mode 100644 new mode 100755 diff --git a/scripts/queries.mjs b/scripts/queries.mjs new file mode 100755 index 00000000..67e9b394 --- /dev/null +++ b/scripts/queries.mjs @@ -0,0 +1,187 @@ +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 = { + 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 = { + 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: '192790171', + }, + reserveAllocationMetricsDailies: { + denom: 'IST', + key: 'Fee', + valueLast: '192790171', + metricsCount: '1', + }, +}; diff --git a/scripts/validateData.mjs b/scripts/validateData.mjs new file mode 100755 index 00000000..7d204120 --- /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 = 'http://localhost:3000/'; +console.log(`API URL set to: ${apiUrl}`); + +const { entity, blockHeight } = process.env; +console.log(`Entity: ${entity}, Block Height: ${blockHeight}`); + +assertAllDefined({ entity, blockHeight }); + +const dailyEntities = ['vaultManagerMetricsDailies', 'reserveAllocationMetricsDailies', 'vaultStatesDailies']; +const filter = dailyEntities.includes(entity) ? { 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(); + console.log('Response:', JSON.stringify(jsonResponse)); + const nodes = jsonResponse?.data[entity]?.nodes; + console.log('Node:', nodes); + + for (const key of Object.keys(expectations[entity])) { + equal(nodes[0]?.[key], expectations[entity][key]); + } +} catch (error) { + console.error('Error:', error); + process.exit(1); +} diff --git a/src/test/mappingHandlers.test.ts b/src/test/mappingHandlers.test.ts index c9b68d7d..09b3eba3 100644 --- a/src/test/mappingHandlers.test.ts +++ b/src/test/mappingHandlers.test.ts @@ -81,114 +81,6 @@ subqlTest( '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,