Skip to content
Merged
Show file tree
Hide file tree
Changes from 12 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
1 change: 1 addition & 0 deletions Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ test-ts:

test-e2e:
yarn workspace @blocksense/e2e-tests run test:scenarios
yarn workspace @blocksense/e2e-tests run test:wit-scenarios

[group('Working with oracles')]
[doc('Build a specific oracle')]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ async function getBlocksenseFeedsCompatibility(
}
const dataFeedId = dataFeed.id;

const { base, quote } = dataFeed.additional_feed_info.pair;
const { base, quote } = dataFeed.additional_feed_info.pair!;

const baseAddress = isSupportedCurrencySymbol(base)
? currencySymbolToDenominationAddress[base]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function addDataProviders(
const dataFeedsWithCryptoResources = await Promise.all(
filteredFeeds.map(async feed => {
const providers = getAllProvidersForPair(
feed.additional_feed_info.pair,
feed.additional_feed_info.pair!,
providersData,
);
return {
Expand All @@ -37,5 +37,5 @@ export async function addDataProviders(

// Filter feeds that have a quote
function filterFeedsWithQuotes(feeds: SimplifiedFeed[]): SimplifiedFeed[] {
return feeds.filter(feed => feed.additional_feed_info.pair.quote);
return feeds.filter(feed => feed.additional_feed_info.pair!.quote);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export function getUniqueDataFeeds(
const seenPairs = new Set<string>();

return dataFeeds.filter(feed => {
const pairKey = pairToString(feed.additional_feed_info.pair);
const pairKey = pairToString(feed.additional_feed_info.pair!);

if (seenPairs.has(pairKey)) {
return false;
Expand All @@ -27,7 +27,7 @@ export function addStableCoinVariants(
feeds: SimplifiedFeed[],
): SimplifiedFeed[] {
const stableCoinVariants = feeds.flatMap(feed => {
const { base, quote } = feed.additional_feed_info.pair;
const { base, quote } = feed.additional_feed_info.pair!;
if (quote in stableCoins) {
return stableCoins[quote as keyof typeof stableCoins]
.map(altStableCoin => createPair(base, altStableCoin))
Expand Down Expand Up @@ -65,7 +65,7 @@ export async function addMarketCapRank(
const asset = cmcMarketCap.find(
asset =>
asset.symbol.toLowerCase() ===
feed.additional_feed_info.pair.base.toLowerCase(),
feed.additional_feed_info.pair!.base.toLowerCase(),
);
return {
...feed,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function updateExchangesArgumentConfig(): Promise<NewFeedsConfig> {
for (const feed of feedsConfig.feeds) {
const pair = feed.additional_feed_info.pair;
const initialExchangePrices = getExchangesPriceDataForPair(
pair,
pair!,
providersData,
);
const outlierExchanges = detectPriceOutliers(
Expand All @@ -44,14 +44,14 @@ export async function updateExchangesArgumentConfig(): Promise<NewFeedsConfig> {

normalizedProvidersData = removePriceOutliers(
providersData,
pair,
pair!,
outlierExchanges,
);
}

const updatedFeedConfig = feedsConfig.feeds.map(feed => {
const providers = getAllProvidersForPair(
feed.additional_feed_info.pair,
feed.additional_feed_info.pair!,
normalizedProvidersData,
);

Expand Down
49 changes: 38 additions & 11 deletions apps/dev/src/commands/decoder/generate-decoder/generate-decoder.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { exec } from 'child_process';
import fs from 'fs/promises';
import path from 'path';
import { promisify } from 'util';

import { Effect } from 'effect';
import { Command, Options } from '@effect/cli';
import { Command as Exec } from '@effect/platform';
import { NodeContext } from '@effect/platform-node';
import chalk from 'chalk';

import { rootDir, valuesOf } from '@blocksense/base-utils';
import { expandJsonFields } from '@blocksense/decoders/expand-wit-json';
import { generateDecoders } from '@blocksense/decoders/generate-decoders';

const execPromise = promisify(exec);

export const generateDecoder = Command.make(
'generate-decoder',
{
stride: Options.integer('stride').pipe(Options.withDefault(0)),
decoderType: Options.choice('decoder-type', ['ssz', 'encode-packed']).pipe(
Options.withDefault('ssz'),
),
Expand All @@ -35,28 +34,53 @@ export const generateDecoder = Command.make(
Options.withDefault('generated-decoders'),
),
},
({ decoderType, evmVersion, outputDir, witFunction, witPath, witWorld }) =>
({
decoderType,
evmVersion,
outputDir,
stride,
witFunction,
witPath,
witWorld,
}) =>
Effect.gen(function* () {
const witFilePath = path.join(rootDir, witPath);
if (!(yield* Effect.tryPromise(() => fs.stat(witFilePath)))) {
return yield* Effect.fail(`WIT file not found at path: ${witFilePath}`);
}

// Generate temporary JSON representation from WIT file
const tempOutputPath = path.join(rootDir, 'tmp/wit-output.json');
yield* Effect.tryPromise(() =>
fs.mkdir(path.dirname(tempOutputPath), { recursive: true }),
);

const args = [
'--input',
path.join(rootDir, witPath),
'--output',
tempOutputPath,
'--world',
witWorld,
'--function',
witFunction,
];
const res = yield* Effect.tryPromise(() =>
execPromise(`wit-converter ${args.join(' ')}`, {
cwd: path.join(rootDir, 'apps/wit-converter'),
}),

yield* Exec.make('wit-converter', ...args).pipe(
Exec.workingDirectory(path.join(rootDir, 'apps/wit-converter')),
Exec.string,
Effect.provide(NodeContext.layer),
);

const witJson = JSON.parse(res.stdout);
const readWitOutput = yield* Effect.tryPromise(() =>
fs.readFile(tempOutputPath, 'utf-8'),
);

// Clean up temporary file
yield* Effect.tryPromise(() => fs.unlink(tempOutputPath));

const witJson = JSON.parse(readWitOutput);

const containsUnion = valuesOf(witJson.types).some(
(field: any) => field.type === 'union',
);
Expand All @@ -71,13 +95,16 @@ export const generateDecoder = Command.make(
const outputPath = path.join(rootDir, outputDir);
yield* Effect.tryPromise(() => fs.mkdir(outputPath, { recursive: true }));

// `2 ^ (n + 1)` divided by 8, rounded up
const prefixSize = Math.floor((stride + 5 + 7) / 8);

const contractPaths = yield* Effect.tryPromise(() =>
generateDecoders(
decoderType,
evmVersion,
outputPath,
fields[witJson.payloadTypeName],
{ containsUnion },
{ containsUnion, prefixSize },
),
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export const PriceFeedConfigCard = ({ feed }: DataFeedCardProps) => {
title: 'Price Feed Configuration',
description: '',
items: [
{ label: 'Base', value: feed.additional_feed_info.pair.base },
{ label: 'Quote', value: feed.additional_feed_info.pair.quote },
{ label: 'Base', value: feed.additional_feed_info.pair?.base },
{ label: 'Quote', value: feed.additional_feed_info.pair?.quote },
{ label: 'Decimals', value: feed.additional_feed_info.decimals },
{ label: 'Category', value: feed.additional_feed_info.category },
],
Expand Down
2 changes: 2 additions & 0 deletions apps/e2e-tests/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
generated-decoders/
cache/
5 changes: 4 additions & 1 deletion apps/e2e-tests/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
"ts": "yarn node --import tsx",
"test": "vitest run --typecheck --coverage",
"test:unit": "yarn vitest -w false src/utils",
"test:scenarios": "yarn test src/test-scenarios/**/e2e.spec.ts"
"test:scenarios": "yarn test src/test-scenarios/general/e2e.spec.ts",
"test:wit-scenarios": "yarn test src/test-scenarios/wit/e2e.spec.ts"
},
"dependencies": {
"@blocksense/base-utils": "workspace:*",
"@blocksense/config-types": "workspace:*",
"@blocksense/contracts": "workspace:*",
"@blocksense/dev": "workspace:*",
"@chainsafe/bls": "^8.2.0",
"@effect/cluster": "^0.48.2",
"@effect/experimental": "^0.54.6",
Expand All @@ -26,6 +28,7 @@
"parse-prometheus-text-format": "^1.1.1",
"tsx": "^4.20.5",
"typescript": "5.9.2",
"viem": "^2.38.6",
"vitest": "^3.2.4"
},
"devDependencies": {
Expand Down
23 changes: 18 additions & 5 deletions apps/e2e-tests/src/test-scenarios/general/e2e.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ import { rgSearchPattern } from '../../utils/utilities';
import { expectedPCStatuses03 } from './expected-service-status';

describe.sequential('E2E Tests with process-compose', () => {
const testEnvironment = `e2e-general`;
const testScenario = 'general';
const testEnvironment = `e2e-${testScenario}`;
const network = 'ink_sepolia';
const MAX_HISTORY_ELEMENTS_PER_FEED = 8192;

Expand All @@ -67,7 +68,7 @@ describe.sequential('E2E Tests with process-compose', () => {
const res = await pipe(
Effect.gen(function* () {
processCompose = yield* EnvironmentManager;
yield* processCompose.start(testEnvironment);
yield* processCompose.start(testScenario);
hasProcessComposeStarted = true;

if (!process.listenerCount('SIGINT')) {
Expand Down Expand Up @@ -253,7 +254,8 @@ describe.sequential('E2E Tests with process-compose', () => {

// Make sure that the feeds info is updated
for (const [id, data] of entriesOf(feedInfoAfterUpdates)) {
const { round: roundAfterUpdates, value: valueAfterUpdates } = data;
const { round: roundAfterUpdates, value } = data;
const valueAfterUpdates = Number(value.slice(0, 50));
// Pegged asset with 10% tolerance should be pegged
// Pegged asset with 0.000001% tolerance should not be pegged
if (id === '50000') {
Expand All @@ -268,11 +270,22 @@ describe.sequential('E2E Tests with process-compose', () => {
feed =>
feed.update_number === updatesToNetworks[network]['0:' + id] - 1,
);

const decimals = feedsConfig.feeds.find(f => f.id.toString() === id)!
.additional_feed_info.decimals;

expect(valueAfterUpdates / 10 ** decimals).toBeCloseTo(
historyData!.value.Numerical,
if (
typeof historyData!.value !== 'object' ||
!('Numerical' in historyData!.value)
) {
return yield* Effect.fail(
new Error('Unexpected feed value type in history'),
);
}

const historyValue = historyData!.value.Numerical;
expect(Number(valueAfterUpdates) / 10 ** decimals).toBeCloseTo(
historyValue,
);

const expectedNumberOfUpdates =
Expand Down
Loading