Skip to content

Entropy tester #2762

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

Merged
merged 10 commits into from
Jun 10, 2025
Merged

Entropy tester #2762

merged 10 commits into from
Jun 10, 2025

Conversation

m30m
Copy link
Collaborator

@m30m m30m commented Jun 6, 2025

Summary

Utility app to regularly check entropy contracts by making a request and waiting for callback.

Things left to do:

  • Accept custom RPC url
  • Add alerts

Rationale

Additional reliability of fortuna

How has this been tested?

  • Current tests cover my changes
  • Added new tests
  • Manually tested the code

@m30m m30m requested a review from a team as a code owner June 6, 2025 21:08
Copy link

vercel bot commented Jun 6, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

8 Skipped Deployments
Name Status Preview Comments Updated (UTC)
api-reference ⬜️ Skipped (Inspect) Jun 10, 2025 5:27pm
component-library ⬜️ Skipped (Inspect) Jun 10, 2025 5:27pm
developer-hub ⬜️ Skipped (Inspect) Jun 10, 2025 5:27pm
entropy-debugger ⬜️ Skipped (Inspect) Jun 10, 2025 5:27pm
entropy-explorer ⬜️ Skipped (Inspect) Jun 10, 2025 5:27pm
insights ⬜️ Skipped (Inspect) Jun 10, 2025 5:27pm
proposals ⬜️ Skipped (Inspect) Jun 10, 2025 5:27pm
staking ⬜️ Skipped (Inspect) Jun 10, 2025 5:27pm

@vercel vercel bot temporarily deployed to Preview – staking June 6, 2025 21:12 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-explorer June 6, 2025 21:12 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-debugger June 6, 2025 21:12 Inactive
@vercel vercel bot temporarily deployed to Preview – component-library June 6, 2025 21:12 Inactive
@vercel vercel bot temporarily deployed to Preview – api-reference June 6, 2025 21:12 Inactive
@vercel vercel bot temporarily deployed to Preview – developer-hub June 6, 2025 21:12 Inactive
@vercel vercel bot temporarily deployed to Preview – insights June 6, 2025 21:12 Inactive
@vercel vercel bot temporarily deployed to Preview – proposals June 6, 2025 21:12 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-explorer June 6, 2025 21:18 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-debugger June 6, 2025 21:18 Inactive
@vercel vercel bot temporarily deployed to Preview – staking June 6, 2025 21:18 Inactive
@vercel vercel bot temporarily deployed to Preview – component-library June 6, 2025 21:18 Inactive
@vercel vercel bot temporarily deployed to Preview – proposals June 6, 2025 21:18 Inactive
@vercel vercel bot temporarily deployed to Preview – insights June 6, 2025 21:18 Inactive
@vercel vercel bot temporarily deployed to Preview – developer-hub June 6, 2025 21:18 Inactive
@vercel vercel bot temporarily deployed to Preview – api-reference June 6, 2025 21:18 Inactive
Copy link
Collaborator

@cprussin cprussin left a comment

Choose a reason for hiding this comment

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

Most important changes IMO are to upgrade tooling to modern practices and more strict configs, I suggest getting in this habit sooner than later especially as packages get copied around as boilerplate

"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-non-null-assertion": "off",
},
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

A few notes:

  1. .eslintrc.js is a deprecated config format
  2. This is a pretty loose config that won't catch a ton of issues, including many issues that make the type system actually reliable and trustworthy.

The easiest fix is to replace this file with a file eslint.config.js that exports my canned config, e.g. something like this. Note you'll need to set "type": "module" in your package.json to use this as I expect esm for all packages I support.

Comment on lines 5 to 6
"main": "lib/index.js",
"types": "lib/index.d.ts",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Note that in modern js packages, it is recommended to use subpath exports in addition to main and types at the root, as eventually subpath exports will be the only supported mechanism.

Comment on lines 10 to 21
"scripts": {
"build": "tsc",
"fix:format": "prettier --write \"src/**/*.ts\"",
"fix:lint": "eslint src/ --fix --max-warnings 0",
"test:format": "prettier --check \"src/**/*.ts\"",
"test:lint": "eslint src/ --max-warnings 0",
"start": "node lib/index.js",
"dev": "ts-node src/index.ts",
"prepublishOnly": "pnpm run build && pnpm run test:lint",
"preversion": "pnpm run test:lint",
"version": "pnpm run test:format && pnpm run test:lint && git add -A src"
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest modeling your scripts after another app, e.g. https://github.com/pyth-network/pyth-crosschain/blob/main/apps/entropy-explorer/package.json#L9-L21 -- many of the scripts here don't make any sense for a package that isn't published like this and you're missing things like having prettier format all valid file types

Comment on lines 37 to 38
"eslint": "^8.13.0",
"jest": "^29.7.0",
Copy link
Collaborator

Choose a reason for hiding this comment

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

In general you should use catalog: dependencies for anything that's listed in the workspace catalog. Doing so will enable me to maintain the versions as I upgrade shared monorepo dependencies.

At a minimum I would ask that you do this for code checking tools like eslint, jest, prettier, etc.

"keywords": [],
"author": "",
"license": "Apache-2.0",
"packageManager": "[email protected]"
Copy link
Collaborator

Choose a reason for hiding this comment

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

This field is not necessary on a workspace package, it should only be specified at the root.

`Multiple contracts found for chain ${config["chain-id"]}, check contract manager store.`,
);
}
loadedConfigs.push({ contract: contracts[0], interval });
Copy link
Collaborator

Choose a reason for hiding this comment

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

Doing:

const foo = [];
for (const bar of bars) {
  foo.push(getSomeValueFrom(bar));
}

is just a procedural equivalent to:

const foo = bars.map(bar => getSomeValueFrom(bar))

I generally recommend getting in the habit of the declarative map over the procedural loop


// eslint-disable-next-line no-constant-condition
while (true) {
await new Promise((resolve) => setTimeout(resolve, 2000));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Don't do this, but for your entertainment, if you want some very esoteric node facts, you can actually do this:

import { promisify } from "util";

await promisify(setTimeout)(2000);

You wouldn't expect it to work due to the argument order of setTimeout, but this works because of some absolutely wild Node internals where the promisify function actually can return a completely separate implementation which is defined in the Node lib internals.

}
const privateKey = toPrivateKey(
fs
.readFileSync(argv["private-key"], "utf-8")
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest using fs/promises and making this async/await. readFileSync is largely unnecessary now that async/await works, and using it at all is kind of a bad habit because it really only serves to mask the async nature of what you're doing, and in some cases it can unintentionally cause major issues because code gets deferred that doesn't need to be.

The only case I recommend using readFileSync or other such sync functions is if you absolutely must add code like this in a place where the code is not designed for async, and converting it would be a huge pain. But here, that's not the case, you're already in an async function.

"Path to the private key to sign the transactions with. Should be hex encoded",
},
},
handler: async (argv: any) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should never use any; yargs will properly typecheck the arguments so the annotation shouldn't even be needed and adding it just cripples the type system. any is a cancer and it will spread and cause the type checker to silently stop verifying a lot more of your code than you probably intend.

If you must, use unknown, but never use any.

},
"include": ["src"],
"exclude": ["node_modules", "**/__tests__/*"]
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I suggest using my canned tsconfig as a base here, as that will enable a lot of much stricter configs which make the type system much more reliable / trustworthy. You can use it like this if you decide to do so

@vercel vercel bot temporarily deployed to Preview – component-library June 9, 2025 22:39 Inactive
@vercel vercel bot temporarily deployed to Preview – proposals June 9, 2025 22:39 Inactive
@vercel vercel bot temporarily deployed to Preview – api-reference June 9, 2025 22:39 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-debugger June 9, 2025 22:39 Inactive
@vercel vercel bot temporarily deployed to Preview – component-library June 9, 2025 22:42 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-explorer June 9, 2025 22:42 Inactive
@vercel vercel bot temporarily deployed to Preview – proposals June 9, 2025 22:42 Inactive
@vercel vercel bot temporarily deployed to Preview – staking June 9, 2025 22:42 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-debugger June 9, 2025 22:42 Inactive
@vercel vercel bot temporarily deployed to Preview – insights June 9, 2025 22:42 Inactive
@vercel vercel bot temporarily deployed to Preview – api-reference June 9, 2025 22:42 Inactive
Copy link
Collaborator

@cprussin cprussin left a comment

Choose a reason for hiding this comment

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

Main piece of feedback is to switch to using zod to validate rather than using typecasting for external data, but other than that this LGTM

async function loadConfig(configPath: string): Promise<LoadedConfig[]> {
const configs = (await import(configPath, {
with: { type: "json" },
})) as { default: ParsedConfig[] };
Copy link
Collaborator

Choose a reason for hiding this comment

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

For all the same reasons you use serde to deserialize in Rust and you don't just unsafe cast external data, we should also avoid typecasting in typescript and should instead validate the schema using zod: https://v3.zod.dev/ (note we still use v3 everywhere in the monorepo but you're welcome to try v4 if you want). This would look basically like this:

const configSchema = z.array(z.strictObject({
  "chain-id": z.string(),
  interval: z.string(),
}));

// ...

const configs = configSchema.parse(
  (await import(configPath, { with: { type: 'json' } })).default
);

Comment on lines 56 to 66
if (contracts.length === 0 || !contracts[0]) {
throw new Error(
`Can not find the contract for chain ${config["chain-id"]}, check contract manager store.`,
);
}
if (contracts.length > 1) {
throw new Error(
`Multiple contracts found for chain ${config["chain-id"]}, check contract manager store.`,
);
}
return { contract: contracts[0], interval };
Copy link
Collaborator

Choose a reason for hiding this comment

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

Marginally better here is to store contracts[0] in a variable and reuse that:

const firstContract = contracts[0];

if (contracts.length === 0 || !firstContract) {
  /* ... */
} else if (contracts.length > 1) {
  /* ... */
} else {
  return { contract: firstContract, interval }
}

The reason this is preferable is that typescript can guarantee statically with this code that firstContract is not undefined in the return branch, but it cannot guarantee the same with contracts[0] due to how typescript narrowing is designed.

};
};
};
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same comment -- don't typecast, instead parse with zod. Typecasting is unsafe and it breaks all the type safety the type checker attempts to provide.

describe: "run the tester until manually stopped",
builder: RUN_OPTIONS,
handler: async (
argv: ArgumentsCamelCase<InferredOptionTypes<typeof RUN_OPTIONS>>,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm yargs should be able to infer this type automatically, are you not finding that to be the case?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

correct

@@ -0,0 +1,5 @@
{
"extends": "@cprussin/tsconfig/nextjs.json",
"include": ["svg.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
Copy link
Collaborator

Choose a reason for hiding this comment

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

You should remove the first and last option here give you aren't in a next app so there's no .next folder at all, and you have no svgs so the first one doesn't make sense

@vercel vercel bot temporarily deployed to Preview – insights June 10, 2025 01:04 Inactive
@vercel vercel bot temporarily deployed to Preview – proposals June 10, 2025 01:04 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-explorer June 10, 2025 01:04 Inactive
@vercel vercel bot temporarily deployed to Preview – api-reference June 10, 2025 01:04 Inactive
@vercel vercel bot temporarily deployed to Preview – component-library June 10, 2025 01:04 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-debugger June 10, 2025 01:04 Inactive
@vercel vercel bot temporarily deployed to Preview – developer-hub June 10, 2025 01:04 Inactive
@vercel vercel bot temporarily deployed to Preview – staking June 10, 2025 01:04 Inactive
@vercel vercel bot temporarily deployed to Preview – component-library June 10, 2025 17:27 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-debugger June 10, 2025 17:27 Inactive
@vercel vercel bot temporarily deployed to Preview – entropy-explorer June 10, 2025 17:27 Inactive
@vercel vercel bot temporarily deployed to Preview – proposals June 10, 2025 17:27 Inactive
@vercel vercel bot temporarily deployed to Preview – api-reference June 10, 2025 17:27 Inactive
@vercel vercel bot temporarily deployed to Preview – insights June 10, 2025 17:27 Inactive
@vercel vercel bot temporarily deployed to Preview – staking June 10, 2025 17:27 Inactive
@vercel vercel bot temporarily deployed to Preview – developer-hub June 10, 2025 17:27 Inactive
@m30m m30m merged commit 21e15cc into main Jun 10, 2025
11 checks passed
@m30m m30m deleted the entropy-tester branch June 10, 2025 17:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants