Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test vaults and reserve indexing #38

Merged
merged 1 commit into from
Dec 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions .github/workflows/liquidation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
79 changes: 79 additions & 0 deletions .github/workflows/vaults-and-reserve-metrics-testing.yml
Original file line number Diff line number Diff line change
@@ -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

Copy link
Collaborator Author

@rabi-siddique rabi-siddique Dec 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a lesser waiting period it tends to fail:

./scripts/validateData.mjs
API URL set to: http://localhost:3000/
Entity: vaults, Block Height: 742
Error: (TypeError#1)
TypeError#1: fetch failed
  at Function.captureStackTrace (file:///home/runner/work/agoric-subql/agoric-subql/node_modules/ses/src/error/tame-v8-error-constructor.js:229:9)
  at node:internal/deps/undici/undici:12618:11
  at async file:///home/runner/work/agoric-subql/agoric-subql/scripts/validateData.mjs:24:20
TypeError#1 cause: (SocketError#2)
Nested error under TypeError#1
  SocketError#2: other side closed
    at Socket.onSocketEnd (node:internal/deps/undici/undici:9169:26)
    at Socket.emit (node:events:529:35)
    at endReadableNT (node:internal/streams/readable:1400:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

At 60 seconds wait, http://localhost:3000 consistently works and test pass.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helpful to include a comment with what value you've found to be too small

Alternately, scripts/validateData.mjs could have a "wait and retry" but this is fine

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rabi-siddique I agree with Turadg's wait and retry suggestion. Such hardcoded sleep times cause flakiness in future. Something like following can be done (as a follow-up)

- name: Wait for GraphQL server to be ready
  run: |
    echo "Waiting for GraphQL server to be ready..."
    until curl -s -o /dev/null -w "%{http_code}" http://localhost:4000/graphql | grep -q "200"; do
      echo "GraphQL server is not ready yet. Retrying in 5 seconds..."
      sleep 5
    done
    echo "GraphQL server is ready!"
  shell: bash

- 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
1 change: 1 addition & 0 deletions scripts/changePrice.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,5 @@ try {
console.log('Standard output:', stdout);
} catch (error) {
console.error('Error:', error);
process.exit(1);
}
3 changes: 2 additions & 1 deletion scripts/checkLiquidation.mjs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -118,4 +118,5 @@ try {
console.log('Validation successful for liquidated vaults.');
} catch (error) {
console.error('Validation failed:', error);
process.exit(1);
}
Empty file modified scripts/createVault.mjs
100644 → 100755
Empty file.
3 changes: 1 addition & 2 deletions scripts/getActiveVaults.mjs
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Empty file modified scripts/lockdown.mjs
100644 → 100755
Empty file.
Empty file modified scripts/placeBid.mjs
100644 → 100755
Empty file.
187 changes: 187 additions & 0 deletions scripts/queries.mjs
Original file line number Diff line number Diff line change
@@ -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',
},
};
42 changes: 42 additions & 0 deletions scripts/validateData.mjs
Original file line number Diff line number Diff line change
@@ -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);
}
Loading
Loading