forked from pendle-finance/external-integration
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvalidate-config.js
130 lines (99 loc) · 3.79 KB
/
validate-config.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
const fs = require('fs');
const path = require('path');
function isValidEthereumAddress(address) {
const ethereumAddressPattern = /^0x[a-fA-F0-9]{40}$/;
return ethereumAddressPattern.test(address);
}
function isKebabCase(str) {
const kebabCaseRegex = /^[a-z0-9]+(-[a-z0-9]+)*$/;
return kebabCaseRegex.test(str);
}
async function main() {
const CHANGED_PROTOCOLS = process.env.CHANGED_PROTOCOLS;
if (!CHANGED_PROTOCOLS) {
console.log('No changed protocols');
return;
}
const protocols = CHANGED_PROTOCOLS.split('\n');
console.log('Currently validating protocols:', protocols);
protocols.forEach((protocol) => validateConfig(protocol));
console.log('Everything is fine.....')
}
function validateConfig(protocol) {
if (!isKebabCase(protocol)) {
throw new Error(`protocol ${protocol}: protocol name must be in kebab-case`);
}
const protocolsPath = path.join(__dirname, 'protocols', protocol);
// check protocol folder exists or not, if not exists we bypass cause it's a deleted protocol
try {
const stats = fs.statSync(protocolsPath);
if (!stats.isDirectory()) {
throw new Error(`protocol ${protocol}: protocols/${protocol} is a file, not a folder`);
}
} catch (err) {
if (err.code === 'ENOENT') {
// folder not exists
return;
} else {
throw new Error(`protocol ${protocol}: An error occur when read protocol folder: ${err}`);
}
}
const configPath = path.join(protocolsPath, 'config.json');
if (!fs.existsSync(configPath)) {
throw new Error(`protocol ${protocol}: config.json not found`);
}
const protocolConfigStr = fs.readFileSync(configPath, 'utf8');
const protocolConfig = JSON.parse(protocolConfigStr);
if (typeof protocolConfig !== 'object'){
throw new Error(`protocol ${protocol}: config is not an object`);
}
const {name, icon, metadata} = protocolConfig;
if (!mustBeNonEmptyString(name)) {
throw new Error(`protocol ${protocol}: invalid field 'name'`);
}
if (!mustBeNonEmptyString(icon)) {
throw new Error(`protocol ${protocol}: invalid field 'icon'`);
}
if (!(icon.endsWith('.png') && icon.length > 4)) {
throw new Error(`protocol ${protocol}: icon must be a valid png image`);
}
if (typeof metadata !== 'object') {
throw new Error(`protocol ${protocol}: invalid field 'metadata'`);
}
const iconPath = path.join(protocolsPath, icon);
if (!fs.existsSync(iconPath)) {
throw new Error(`protocol ${protocol}: icon path not found for protocol ${icon}`);
}
const {pt, yt, lp} = metadata;
checkMetadataField(pt, protocol, 'pt');
checkMetadataField(yt, protocol, 'yt');
checkMetadataField(lp, protocol, 'lp');
}
function mustBeNonEmptyString(str) {
return typeof str === 'string' && str.trim() !== '';
}
function checkMetadataField(data, protocol, field) {
if (data === null || data === undefined) {
return;
}
if (!Array.isArray(data)) {
throw new Error(`protocol ${protocol}: metadata ${field} must be an array`)
}
for (let index = 0; index < data.length; index ++) {
const item = data[index];
const {chainId, address, description, integrationUrl} = item;
if (typeof chainId !== 'number') {
throw new Error(`protocol ${protocol}: metadata ${field} invalid 'chainId' field at index ${index}`);
}
if (!mustBeNonEmptyString(address) || !isValidEthereumAddress(address)) {
throw new Error(`protocol ${protocol}: metadata ${field} invalid 'address' field at index ${index}`);
}
if (!mustBeNonEmptyString(description)) {
throw new Error(`protocol ${protocol}: metadata ${field} invalid 'description' field at index ${index}`);
}
if (!mustBeNonEmptyString(integrationUrl)) {
throw new Error(`protocol ${protocol}: metadata ${field} invalid 'integrationUrl' field at index ${index}`);
}
}
}
void main()