Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

Even more improved token validation script #1153

Merged
merged 22 commits into from
Jan 21, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e84a82e
typescript sourcemap: true
randomshinichi Jan 15, 2024
0934873
implemented canOnlyAddOneToken(), detectDuplicateSymbol()
randomshinichi Jan 15, 2024
51b0cb3
ValidationError.INVALID_MINT: some mints are PDAs and won't be on the…
randomshinichi Jan 16, 2024
1dbee0c
Record.Community Validated: bool -> string
randomshinichi Jan 16, 2024
149b2a1
rm parse.ts
randomshinichi Jan 16, 2024
e1fa61f
validate.ts: complete validation functions
randomshinichi Jan 16, 2024
0580312
exec() was showing the output of 'git show' even when stdout was redi…
randomshinichi Jan 16, 2024
f282153
main.ts: functionality complete
randomshinichi Jan 16, 2024
d8ab4bb
removed unused function in validate.ts
randomshinichi Jan 16, 2024
65c3e6f
exceptions: some tokens don't need to have communityValidated: true
randomshinichi Jan 16, 2024
28cf097
use ValidatedTokensData which existed already, change 'Community Vali…
randomshinichi Jan 16, 2024
d2a034a
remove exceptions for community validated
randomshinichi Jan 17, 2024
3c8ea7a
validMintAddress(): mints don't have to be on the edd25519 curve, rem…
randomshinichi Jan 17, 2024
c643732
ValidatedTokensData: keep track of which line it was in the CSV
randomshinichi Jan 17, 2024
4de1c96
rework duplicate symbol detection, abstract out file reading, csv par…
randomshinichi Jan 17, 2024
da29652
noEditsToPreviousLinesAllowed()
randomshinichi Jan 18, 2024
34743ea
better validation error messages. a better message tells you what to do
randomshinichi Jan 18, 2024
5aad79a
rework detectDuplicateSymbol()
randomshinichi Jan 18, 2024
9ae1282
split logic out, so one can run it with Github Actions (which doesn't…
randomshinichi Jan 18, 2024
3fd2078
revive github action for validate-PR
randomshinichi Jan 19, 2024
defaac4
improve duplicate symbol detection: people may not submit tokens that…
randomshinichi Jan 21, 2024
8105f66
exit code is the number of errors. this is useful for github actions …
randomshinichi Jan 21, 2024
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 package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
"@actions/exec": "^1.1.1",
"@actions/github": "^5.1.1",
"@solana/web3.js": "^1.73.2",
"@types/minimist": "^1.2.5",
"csv-writer": "^1.6.0",
"minimist": "^1.2.8",
"node-downloader-helper": "^2.1.6",
"node-fetch": "^2.6.6"
},
Expand Down
12 changes: 12 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { validateValidatedTokensCsv } from "./logic";
import minimist from "minimist";
// CLI entrypoint which accepts an argument
(async () => {
try {
const argv = minimist(process.argv.slice(2));
await validateValidatedTokensCsv(argv._[0]);
}
catch (error: any) {
console.log(error.message)
}
})();
90 changes: 90 additions & 0 deletions src/logic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import * as core from "@actions/core";
import { exec } from "@actions/exec";
import { canOnlyAddOneToken, detectDuplicateSymbol, detectDuplicateMints as detectDuplicateMints, validMintAddress, noEditsToPreviousLinesAllowed } from "./utils/validate";
import { ValidatedTokensData } from "./types/types";
import { indexToLineNumber } from "./utils/validate";
import { parse } from "csv-parse/sync";
import fs from "fs";

export async function validateValidatedTokensCsv(filename: string) {
const [records, recordsRaw] = parseCsv(filename);

const recordsPreviousRaw = await gitPreviousVersion("validated-tokens.csv");
fs.writeFileSync(".validated-tokens-0.csv", recordsPreviousRaw);
randomshinichi marked this conversation as resolved.
Show resolved Hide resolved
const [recordsPrevious, _] = parseCsv(".validated-tokens-0.csv")

let duplicateSymbols;
let duplicateMints;
let attemptsToAddMultipleTokens;
let invalidMintAddresses;
let notCommunityValidated;
let noEditsAllowed;

duplicateSymbols = detectDuplicateSymbol(recordsPrevious, records);
duplicateMints = detectDuplicateMints(records);
attemptsToAddMultipleTokens = canOnlyAddOneToken(recordsPrevious, records)
invalidMintAddresses = validMintAddress(records);
noEditsAllowed = noEditsToPreviousLinesAllowed(recordsPrevious, records);
// notCommunityValidated = validCommunityValidated(records);

console.log("No More Duplicate Symbols:", duplicateSymbols);
console.log("Duplicate Mints:", duplicateMints);
console.log("Attempts to Add Multiple Tokens:", attemptsToAddMultipleTokens);
console.log("Invalid Mint Addresses:", invalidMintAddresses);
console.log("Not Community Validated:", notCommunityValidated);
console.log("Edits to Existing Tokens:", noEditsAllowed);
}

// Get previous version of validated-tokens.csv from last commit
async function gitPreviousVersion(path: string): Promise<any> {
let prevVersion = "";
let gitCmdError = "";

try {
await exec("git", ["show", `origin/main:${path}`], {
listeners: {
stdout: (data: Buffer) => {
prevVersion += data.toString();
},
stderr: (data: Buffer) => {
gitCmdError += data.toString();
},
},
silent: true
});
} catch (error: any) {
core.setFailed(error.message);
}

if (gitCmdError) {
core.setFailed(gitCmdError);
}
return prevVersion;
}

function parseCsv(filename: string): [ValidatedTokensData[], string] {
const recordsRaw = fs.readFileSync(filename, "utf8")
const r = parse(recordsRaw, {
columns: true,
skip_empty_lines: true,
});
const records = csvToRecords(r);
return [records, recordsRaw];
}

function csvToRecords(r: any): ValidatedTokensData[] {
const records: ValidatedTokensData[] = [];
r.forEach((record: any, i: number) => {
const rec: ValidatedTokensData = {
Name: record.Name,
Symbol: record.Symbol,
Mint: record.Mint,
Decimals: record.Decimals,
LogoURI: record.LogoURI,
"Community Validated": JSON.parse(record["Community Validated"]),
Line: indexToLineNumber(i)
};
records.push(rec);
});
return records;
}
77 changes: 7 additions & 70 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,12 @@
import * as core from "@actions/core";
import { exec } from "@actions/exec";
import { parseGitPatch } from "./utils/parse";
import { validateGitPatch } from "./utils/validate";
import { getValidated } from "./utils/get-jup-strict";
import { ValidatedSet, ValidationError } from "./types/types";
import { parse } from "csv-parse/sync";
import fs from "fs";
import assert from "assert";

function validateValidatedTokensCsv() {
const records = parse(fs.readFileSync("validated-tokens.csv", "utf8"), {
columns: true,
skip_empty_lines: true,
});
assert.deepStrictEqual(Object.keys(records[0]), [
"Name",
"Symbol",
"Mint",
"Decimals",
"LogoURI",
"Community Validated",
]);
}

// Validates diff between validated-tokens.csv in the branch vs origin/main
async function getDiffAndValidate(): Promise<void> {
let gitDiff = "";
let gitDiffError = "";

import { validateValidatedTokensCsv } from "./logic";
// Github Actions entrypoint
(async () => {
try {
await exec("git", ["diff", "origin/main", "validated-tokens.csv"], {
listeners: {
stdout: (data: Buffer) => {
gitDiff += data.toString();
},
stderr: (data: Buffer) => {
gitDiffError += data.toString();
},
},
});
} catch (error: any) {
core.setFailed(error.message);
}

if (gitDiffError) {
core.setFailed(gitDiffError);
await validateValidatedTokensCsv("validated-tokens.csv");
}

// core.debug(`Git diff: ${gitDiff}`)

// Get Jup tokens that are in the strict list to check for duplicates.
let validatedSet: ValidatedSet;
try {
validatedSet = await getValidated();

const errors: ValidationError[][] = [];

parseGitPatch(gitDiff).forEach((patch) => {
const patchErrors = validateGitPatch(patch, validatedSet);
if (patchErrors && patchErrors.length > 0) {
errors.push(patchErrors);
}
});

if (errors.length > 0) {
core.setFailed(errors.join(","));
}
} catch (error: any) {
catch (error: any) {
core.setFailed(error.message);
console.log(error.message)
}
}

validateValidatedTokensCsv();
// getDiffAndValidate();
})();
8 changes: 5 additions & 3 deletions src/types/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,13 @@ export enum ValidationError {
UNRELATED_CODE = "Changes to unrelated code are not allowed",
MULTIPLE_TOKENS = "Only one token can be added at a time",
DUPLICATE_NAME = "Token name already exists",
DUPLICATE_SYMBOL = "Token symbol already exists",
DUPLICATE_SYMBOL = "Token symbol already exists, please forbid even more duplicates",
DUPLICATE_MINT = "Mint already exists",
INVALID_MINT = "Invalid mint address, not on ed25519 curve",
INVALID_MINT = "Invalid mint address, not base58 decodable",
INVALID_DECIMALS = "Invalid decimals",
INVALID_IMAGE_URL = "Invalid image URL",
INVALID_COMMUNITY_VALIDATED = "Invalid community validated",
CHANGES_DISCOURAGED = "Tokens already in the CSV should not be edited"
}

export interface WormholeData {
Expand All @@ -97,5 +98,6 @@ export interface ValidatedTokensData {
Mint: string;
Decimals: string;
LogoURI: string;
"Community Validated": "false" | "true";
"Community Validated": boolean;
Line: number;
}
65 changes: 0 additions & 65 deletions src/utils/parse.ts

This file was deleted.

Loading