Added checks and readme.md
This commit is contained in:
1 parent
e5a7886b9c
commit
e80494b80f
4 files changed
+231
-13
No files matched your search
Generated
+29
-1
@@ -10,7 +10,8 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"ajv-formats": "^3.0.1"
|
"ajv-formats": "^3.0.1",
|
||||||
|
"image-size": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ajv": {
|
"node_modules/ajv": {
|
||||||
@@ -54,11 +55,38 @@
|
|||||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz",
|
||||||
"integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw=="
|
"integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw=="
|
||||||
},
|
},
|
||||||
|
"node_modules/image-size": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/image-size/-/image-size-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"queue": "6.0.2"
|
||||||
|
},
|
||||||
|
"bin": {
|
||||||
|
"image-size": "bin/image-size.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/inherits": {
|
||||||
|
"version": "2.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||||
|
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||||
|
},
|
||||||
"node_modules/json-schema-traverse": {
|
"node_modules/json-schema-traverse": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
|
||||||
},
|
},
|
||||||
|
"node_modules/queue": {
|
||||||
|
"version": "6.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
|
||||||
|
"integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "~2.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/require-from-string": {
|
"node_modules/require-from-string": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||||
|
|||||||
+3
-2
@@ -4,7 +4,7 @@
|
|||||||
"description": "Vara Network token list",
|
"description": "Vara Network token list",
|
||||||
"main": "scripts/verifier.js",
|
"main": "scripts/verifier.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node scripts/verifier.js"
|
"check": "node scripts/verifier.js"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"vara network",
|
"vara network",
|
||||||
@@ -15,6 +15,7 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ajv": "^8.17.1",
|
"ajv": "^8.17.1",
|
||||||
"ajv-formats": "^3.0.1"
|
"ajv-formats": "^3.0.1",
|
||||||
|
"image-size": "^1.1.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
# Vara Network token list
|
||||||
|
|
||||||
|
## Merge Request Requirements
|
||||||
|
|
||||||
|
### Overview
|
||||||
|
|
||||||
|
This document outlines the requirements for submitting a merge request related to the `Vara Network token list` project.
|
||||||
|
Ensure that all changes adhere to the specified guidelines to maintain consistency and integrity in the token data and
|
||||||
|
related assets.
|
||||||
|
|
||||||
|
### File Naming and Uniqueness
|
||||||
|
|
||||||
|
- **File Names**: All files must have unique names within their respective directories. File names are case-insensitive.
|
||||||
|
|
||||||
|
### JSON File Requirements (`data` Directory)
|
||||||
|
|
||||||
|
1. **File Naming**:
|
||||||
|
- The JSON file name must match the `contractAddress` property of the token and be in lowercase.
|
||||||
|
|
||||||
|
2. **File Extension**:
|
||||||
|
- The file extension must be `.json`.
|
||||||
|
|
||||||
|
3. **Schema Validation**:
|
||||||
|
- The JSON file must conform to the schema defined in `scripts/token-schema.json`. Below is the required schema:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"title": "Token Schema",
|
||||||
|
"description": "Schema for validating token information in a blockchain context.",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the token."
|
||||||
|
},
|
||||||
|
"ticker": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The short name of the token."
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The full name of the network or token."
|
||||||
|
},
|
||||||
|
"iconFileName": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The icon file name for the token."
|
||||||
|
},
|
||||||
|
"infoURL": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri",
|
||||||
|
"description": "URL for additional information about the token."
|
||||||
|
},
|
||||||
|
"contractAddress": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The smart contract address of the token."
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"fungible",
|
||||||
|
"nft"
|
||||||
|
],
|
||||||
|
"description": "The type of token (fungible or NFT)."
|
||||||
|
},
|
||||||
|
"decimals": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "The number of decimal places."
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A description of the token.",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"website": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri",
|
||||||
|
"description": "Link to the project's website.",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"whitepaper": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "uri",
|
||||||
|
"description": "Link to the project's whitepaper.",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"initialSupply": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The initial supply of tokens.",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"totalSupply": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The total supply of tokens.",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"maxSupply": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The maximum supply of tokens.",
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"ticker",
|
||||||
|
"title",
|
||||||
|
"iconFileName",
|
||||||
|
"infoURL",
|
||||||
|
"contractAddress",
|
||||||
|
"type",
|
||||||
|
"decimals"
|
||||||
|
],
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### PNG File Requirements (`icons` Directory)
|
||||||
|
|
||||||
|
1. **File Naming**:
|
||||||
|
- The PNG file name must match the `contractAddress` property of the token and be in lowercase.
|
||||||
|
|
||||||
|
2. **File Extension**:
|
||||||
|
- The file extension must be `.png`.
|
||||||
|
|
||||||
|
3. **File Usage**:
|
||||||
|
- Each PNG file should be used in exactly one JSON file. However, it must be used in at least one JSON file.
|
||||||
|
|
||||||
|
4. **File Dimensions**:
|
||||||
|
- The PNG file must be square and have dimensions of at least 128x128 pixels (but no more than 1024x1024 pixels).
|
||||||
|
|
||||||
|
5. **File Format**:
|
||||||
|
- The file must be in PNG format.
|
||||||
|
|
||||||
|
### Creating a Merge Request
|
||||||
|
|
||||||
|
### Creating a Merge Request
|
||||||
|
|
||||||
|
1. **Verify Functionality**:
|
||||||
|
- Before creating a merge request, ensure that everything works correctly by running the following command:
|
||||||
|
```sh
|
||||||
|
npm run check
|
||||||
|
```
|
||||||
|
- Make sure there are no errors and all functionalities are working as expected.
|
||||||
|
|
||||||
|
2. **Submit Merge Request**:
|
||||||
|
- Once you have verified that everything is working correctly, you can proceed to create a merge request.
|
||||||
+53
-10
@@ -2,15 +2,29 @@ const Ajv = require('ajv');
|
|||||||
const addFormats = require('ajv-formats');
|
const addFormats = require('ajv-formats');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
const sizeOf = require('image-size');
|
||||||
|
|
||||||
const schema = require('./token-schema.json');
|
const schema = require('./token-schema.json');
|
||||||
|
|
||||||
function validateJsonFile(filePath) {
|
const ajv = new Ajv();
|
||||||
|
addFormats(ajv);
|
||||||
|
const validate = ajv.compile(schema);
|
||||||
|
|
||||||
|
const dataDirectoryPath = path.resolve(process.cwd(), 'data');
|
||||||
|
const iconsDirectoryPath = path.resolve(dataDirectoryPath, 'icons');
|
||||||
|
|
||||||
|
function validateJsonFile(filePath, iconUsage) {
|
||||||
try {
|
try {
|
||||||
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
||||||
const valid = validate(data);
|
const valid = validate(data);
|
||||||
if (valid) {
|
if (valid) {
|
||||||
console.log(`File ${path.basename(filePath)} is valid.`);
|
console.log(`File ${path.basename(filePath)} is valid.`);
|
||||||
|
const iconFileName = data.iconFileName.toLowerCase();
|
||||||
|
if (iconUsage[iconFileName]) {
|
||||||
|
iconUsage[iconFileName]++;
|
||||||
|
} else {
|
||||||
|
iconUsage[iconFileName] = 1;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
console.log(`File ${path.basename(filePath)} is invalid:`, validate.errors);
|
console.log(`File ${path.basename(filePath)} is invalid:`, validate.errors);
|
||||||
}
|
}
|
||||||
@@ -19,27 +33,56 @@ function validateJsonFile(filePath) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function validateAllJsonFilesInDirectory(directoryPath) {
|
function validatePngFile(filePath, iconUsage) {
|
||||||
|
if (path.extname(filePath) !== '.png') {
|
||||||
|
throw new Error(`File ${path.basename(filePath)} is invalid: Image must be in PNG format.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const dimensions = sizeOf(filePath);
|
||||||
|
const fileName = path.basename(filePath).toLowerCase();
|
||||||
|
const MIN_SIZE = 128;
|
||||||
|
const MAX_SIZE = 1024;
|
||||||
|
if (dimensions.width !== dimensions.height || dimensions.width < MIN_SIZE || dimensions.width > MAX_SIZE) {
|
||||||
|
throw new Error(`File ${fileName} is invalid: Image must be square and at least ${MIN_SIZE}x${MIN_SIZE} pixels, Your image is ${dimensions.width}x${dimensions.height} pixels.`);
|
||||||
|
} else if (!iconUsage[fileName] || iconUsage[fileName] > 1) {
|
||||||
|
throw new Error(`File ${fileName} is invalid: Icon must be used in exactly one JSON file.`);
|
||||||
|
} else {
|
||||||
|
console.log(`File ${fileName} is valid.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateAllFilesInDirectory(directoryPath, extension, validationFunction, iconUsage) {
|
||||||
fs.readdir(directoryPath, (err, files) => {
|
fs.readdir(directoryPath, (err, files) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('Error reading directory:', err);
|
console.error('Error reading directory:', err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const fileNames = new Set();
|
||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
const filePath = path.join(directoryPath, file);
|
const filePath = path.join(directoryPath, file);
|
||||||
if (path.extname(file) === '.json') {
|
const fileName = path.basename(file, extension).toLowerCase();
|
||||||
validateJsonFile(filePath);
|
|
||||||
|
if (fileNames.has(fileName)) {
|
||||||
|
console.log(`File ${file} is invalid: Duplicate file name (case insensitive).`);
|
||||||
|
} else {
|
||||||
|
fileNames.add(fileName);
|
||||||
|
if (path.extname(file) === extension) {
|
||||||
|
validationFunction(filePath, iconUsage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const ajv = new Ajv();
|
function validateJsonFiles(iconUsage) {
|
||||||
addFormats(ajv);
|
validateAllFilesInDirectory(dataDirectoryPath, '.json', validateJsonFile, iconUsage);
|
||||||
|
}
|
||||||
|
|
||||||
const validate = ajv.compile(schema);
|
function validatePngFiles(iconUsage) {
|
||||||
|
validateAllFilesInDirectory(iconsDirectoryPath, '.png', validatePngFile, iconUsage);
|
||||||
|
}
|
||||||
|
|
||||||
const dataDirectoryPath = path.resolve(process.cwd(), 'data');
|
const iconUsage = {};
|
||||||
|
validateJsonFiles(iconUsage);
|
||||||
validateAllJsonFilesInDirectory(dataDirectoryPath);
|
validatePngFiles(iconUsage);
|
||||||
Reference in new issue
Block a user