Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {addCommand as addFork} from './commands/fork';
import {addCommand as addGovernance} from './commands/governance';
import {addCommand as addIpfsCommand} from './commands/ipfsUpload';
import {addCommand as addCapoCommand} from './commands/capo';
import {addCommand as addCapoSvrCommand} from './commands/capoSvr';

const program = new Command();

Expand All @@ -32,5 +33,6 @@ addDiffSnapshots(program);
addFork(program);
addIpfsCommand(program);
addCapoCommand(program);
addCapoSvrCommand(program);

program.parse();
22 changes: 22 additions & 0 deletions src/commands/capoSvr.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import fs from 'node:fs';
import type {Command} from '@commander-js/extra-typings';
import {generateSvrCapoReport} from '../reports/capo-svr-comparative-report';
import {readJsonFile, readJsonString} from '../utils/json';

export function addCommand(program: Command) {
program
.command('capo-svr-report')
.description('generate a capo svr comparative report')
.argument('<source>')
.option('-o, --out <string>', 'output path')
.option('--stringMode', 'expects input to be a string, not paths')
.action(async (_source, options) => {
const source = options.stringMode ? readJsonString(_source) : readJsonFile(_source);
const content = await generateSvrCapoReport(source);
if (options.out) {
fs.writeFileSync(options.out, content);
} else {
console.log(content);
}
});
}
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ export * from './govv3/generateProposalReport';
export * from './utils/tenderlyClient';
export * from './utils/logger';
export * from './govv3/utils/checkAddress';
export * from './reports/capo-report';
export * from './reports/capo-svr-comparative-report';
37 changes: 37 additions & 0 deletions src/reports/__snapshots__/capo-svr-report.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Bun Snapshot v1, https://goo.gl/fbAQLP

exports[`capo svr report should generate a well formatted capo svr report 1`] = `
"# Capo Comparative Report

# Capped wstETH / stETH(ETH) / USD

- Difference between adapters using SVR and regular Chainlink Feeds

| SVR Adapter | Regular Adapter | Diff | Date |
| --- | --- | --- | --- |
| 1880.1097014 | 1880.16617657 | 0.00% | 12 Apr 2025 |
| 1940.99317901 | 1934.84763392 | 0.32% | 13 Apr 2025 |
| 1951.25160577 | 1948.99310701 | 0.12% | 14 Apr 2025 |
| 1968.85656094 | 1968.56171868 | 0.01% | 15 Apr 2025 |
| 1880.44218254 | 1880.88400462 | 0.02% | 16 Apr 2025 |
| 1927.14919798 | 1921.9665194 | 0.27% | 17 Apr 2025 |
| 1901.98709042 | 1901.24372975 | 0.04% | 18 Apr 2025 |
| 1922.66605311 | 1922.94047495 | 0.01% | 19 Apr 2025 |
| 1908.33882018 | 1906.22505555 | 0.11% | 20 Apr 2025 |
| 1973.33083291 | 1970.15250316 | 0.16% | 21 Apr 2025 |
| 1948.43062491 | 1949.37422474 | 0.05% | 22 Apr 2025 |
| 2160.35296377 | 2171.82424304 | 0.53% | 23 Apr 2025 |
| 2093.83167086 | 2093.91812992 | 0.00% | 24 Apr 2025 |
| 2148.42289872 | 2146.33325394 | 0.10% | 25 Apr 2025 |
| 2146.93062115 | 2146.64704136 | 0.01% | 26 Apr 2025 |
| 2167.39047482 | 2161.98612144 | 0.25% | 27 Apr 2025 |
| 2169.22825978 | 2170.50143613 | 0.06% | 28 Apr 2025 |
| 2183.31686871 | 2183.95464045 | 0.03% | 29 Apr 2025 |
| 2106.14087107 | 2100.66019434 | 0.26% | 30 Apr 2025 |
| 2209.6315434 | 2213.95366061 | 0.20% | 01 May 2025 |
| 2215.33523206 | 2216.96923478 | 0.07% | 02 May 2025 |
| 2207.45309063 | 2207.8434084 | 0.02% | 03 May 2025 |
| 2196.18873716 | 2196.94841401 | 0.03% | 04 May 2025 |
| 2173.76096755 | 2173.72491546 | 0.00% | 05 May 2025 |
"
`;
65 changes: 65 additions & 0 deletions src/reports/capo-svr-comparative-report.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import {formatUnits} from 'viem';
import {CapoSvrSnapshot} from './snapshot-types';

type Comparative = {
regularAdapterPrice: string;
svrAdapterPrice: string;
diff: string;
date: string;
};

export async function generateSvrCapoReport(snapshot: CapoSvrSnapshot) {
let comparative: Comparative[] = [];

for (const key in snapshot.comparative) {
const price = snapshot.comparative[key];

const svrAdapterPrice = formatUnits(BigInt(price.svrAdapterPrice), snapshot.decimals);
const regularAdapterPrice = formatUnits(BigInt(price.regularAdapterPrice), snapshot.decimals);
const difference =
Number(svrAdapterPrice) > Number(regularAdapterPrice)
? Number(svrAdapterPrice) - Number(regularAdapterPrice)
: Number(regularAdapterPrice) - Number(svrAdapterPrice);

const diff = (
(100 * difference) /
((Number(svrAdapterPrice) + Number(regularAdapterPrice)) / 2)
).toFixed(2);

const formattedDate = formatTimestamp(price.timestamp);

comparative.push({
svrAdapterPrice,
regularAdapterPrice,
diff,
date: formattedDate,
});
}

comparative = comparative.slice(snapshot.minSnapshotDelay);

// generate md report
let content = '';
content += `# Capo Comparative Report\n\n`;
content += `# ${snapshot.sourceName} \n\n`;
content += `- Difference between adapters using SVR and regular Chainlink Feeds\n\n`;
content += `| SVR Adapter | Regular Adapter | Diff | Date |\n`;
content += `| --- | --- | --- | --- |\n`;
comparative.forEach((price) => {
content += `| ${price.svrAdapterPrice} | ${price.regularAdapterPrice} | ${price.diff}% | ${price.date} |\n`;
});
return content;
}

function formatTimestamp(timestampInSec: number) {
// Create a new Date object from the timestamp in seconds
const date = new Date(timestampInSec * 1000);

// Use the Intl.DateTimeFormat API to format the date
return new Intl.DateTimeFormat('en-GB', {
year: 'numeric',
month: 'short',
day: '2-digit',
timeZone: 'GMT',
}).format(date);
}
16 changes: 16 additions & 0 deletions src/reports/capo-svr-report.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import {describe, expect, it} from 'vitest';
import {readJsonFile} from '../utils/json';
import {generateSvrCapoReport} from './capo-svr-comparative-report';

describe('capo svr report', () => {
it(
'should generate a well formatted capo svr report',
async () => {
const snapshot = readJsonFile('/src/reports/mocks/capoSvr.json');
const content = await generateSvrCapoReport(snapshot);
console.log(content);
expect(content).toMatchSnapshot();

Check failure on line 12 in src/reports/capo-svr-report.spec.ts

View workflow job for this annotation

GitHub Actions / test / release

src/reports/capo-svr-report.spec.ts > capo svr report > should generate a well formatted capo svr report

Error: Snapshot `capo svr report > should generate a well formatted capo svr report 1` mismatched ❯ it.timeout src/reports/capo-svr-report.spec.ts:12:23
},
{timeout: 30000},
);
});
162 changes: 162 additions & 0 deletions src/reports/mocks/capoSvr.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
{
"comparative": {
"22199900": {
"regularAdapterPrice": 217666375221,
"svrAdapterPrice": 217554419401,
"timestamp": 1743822131
},
"22207200": {
"regularAdapterPrice": 216795440985,
"svrAdapterPrice": 216644202291,
"timestamp": 1743910247
},
"22214500": {
"regularAdapterPrice": 184904466888,
"svrAdapterPrice": 184331232930,
"timestamp": 1743998399
},
"22221800": {
"regularAdapterPrice": 191382628592,
"svrAdapterPrice": 190799419233,
"timestamp": 1744086611
},
"22229100": {
"regularAdapterPrice": 172703894879,
"svrAdapterPrice": 172730277631,
"timestamp": 1744174619
},
"22236400": {
"regularAdapterPrice": 194477533416,
"svrAdapterPrice": 194601135762,
"timestamp": 1744262495
},
"22243700": {
"regularAdapterPrice": 185570748959,
"svrAdapterPrice": 185112817156,
"timestamp": 1744350443
},
"22251000": {
"regularAdapterPrice": 188016617657,
"svrAdapterPrice": 188010970140,
"timestamp": 1744438283
},
"22258300": {
"regularAdapterPrice": 193484763392,
"svrAdapterPrice": 194099317901,
"timestamp": 1744526231
},
"22265600": {
"regularAdapterPrice": 194899310701,
"svrAdapterPrice": 195125160577,
"timestamp": 1744614059
},
"22272900": {
"regularAdapterPrice": 196856171868,
"svrAdapterPrice": 196885656094,
"timestamp": 1744702151
},
"22280200": {
"regularAdapterPrice": 188088400462,
"svrAdapterPrice": 188044218254,
"timestamp": 1744790159
},
"22287500": {
"regularAdapterPrice": 192196651940,
"svrAdapterPrice": 192714919798,
"timestamp": 1744878263
},
"22294800": {
"regularAdapterPrice": 190124372975,
"svrAdapterPrice": 190198709042,
"timestamp": 1744966187
},
"22302100": {
"regularAdapterPrice": 192294047495,
"svrAdapterPrice": 192266605311,
"timestamp": 1745054243
},
"22309400": {
"regularAdapterPrice": 190622505555,
"svrAdapterPrice": 190833882018,
"timestamp": 1745142263
},
"22316700": {
"regularAdapterPrice": 197015250316,
"svrAdapterPrice": 197333083291,
"timestamp": 1745230343
},
"22324000": {
"regularAdapterPrice": 194937422474,
"svrAdapterPrice": 194843062491,
"timestamp": 1745318339
},
"22331300": {
"regularAdapterPrice": 217182424304,
"svrAdapterPrice": 216035296377,
"timestamp": 1745406467
},
"22338600": {
"regularAdapterPrice": 209391812992,
"svrAdapterPrice": 209383167086,
"timestamp": 1745494463
},
"22345900": {
"regularAdapterPrice": 214633325394,
"svrAdapterPrice": 214842289872,
"timestamp": 1745582423
},
"22353200": {
"regularAdapterPrice": 214664704136,
"svrAdapterPrice": 214693062115,
"timestamp": 1745670383
},
"22360500": {
"regularAdapterPrice": 216198612144,
"svrAdapterPrice": 216739047482,
"timestamp": 1745758211
},
"22367800": {
"regularAdapterPrice": 217050143613,
"svrAdapterPrice": 216922825978,
"timestamp": 1745846207
},
"22375100": {
"regularAdapterPrice": 218395464045,
"svrAdapterPrice": 218331686871,
"timestamp": 1745934335
},
"22382400": {
"regularAdapterPrice": 210066019434,
"svrAdapterPrice": 210614087107,
"timestamp": 1746022607
},
"22389700": {
"regularAdapterPrice": 221395366061,
"svrAdapterPrice": 220963154340,
"timestamp": 1746110987
},
"22397000": {
"regularAdapterPrice": 221696923478,
"svrAdapterPrice": 221533523206,
"timestamp": 1746199583
},
"22404300": {
"regularAdapterPrice": 220784340840,
"svrAdapterPrice": 220745309063,
"timestamp": 1746287867
},
"22411600": {
"regularAdapterPrice": 219694841401,
"svrAdapterPrice": 219618873716,
"timestamp": 1746376319
},
"22418900": {
"regularAdapterPrice": 217372491546,
"svrAdapterPrice": 217376096755,
"timestamp": 1746464591
}
},
"decimals": 8,
"minSnapshotDelay": 7,
"sourceName": "Capped wstETH / stETH(ETH) / USD"
}
15 changes: 15 additions & 0 deletions src/reports/snapshot-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,18 @@ export const capoSnapshotSchema = z.object({
});

export type CapoSnapshot = z.infer<typeof capoSnapshotSchema>;

export const capoSvrPriceSchema = z.object({
regularAdapterPrice: z.number(),
svrAdapterPrice: z.number(),
timestamp: z.number(),
});

export const capoSvrSnapshotSchema = z.object({
sourceName: z.string(),
decimals: z.number(),
minSnapshotDelay: z.number(),
comparative: z.record(capoSvrPriceSchema),
});

export type CapoSvrSnapshot = z.infer<typeof capoSvrSnapshotSchema>;
Loading