Skip to content

Commit

Permalink
initialize
Browse files Browse the repository at this point in the history
  • Loading branch information
thismars committed Dec 13, 2022
0 parents commit e2ff674
Show file tree
Hide file tree
Showing 19 changed files with 344 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# typescripts
/src/config.ts

# resources
/node_modules
/shellScripts/gitConfig.sh
package-lock.json
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# validator-identity-crawler
6 changes: 6 additions & 0 deletions nodemon.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"watch": ["src", ".env"],
"ext": "js,ts,json",
"exec": "ts-node -r ./src/server.ts",
"ignore": ["src/scheduler.ts"]
}
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "validator-identity-crawler",
"version": "0.0.1",
"description": "The Official FirmaChain Javascript SDK written in Typescript",
"author": "FirmaChain <[email protected]>",
"private": true,
"license": "UNLICENSED",
"scripts": {
"start": "ts-node src/crawler.ts",
"start:dev": "ts-node src/crawler.ts --watch",
"start:debug": "ts-node src/crawler.ts --debug --watch"
},
"keywords": [],
"devDependencies": {
"ts-node": "^10.9.1",
"typescript": "^4.9.4"
},
"dependencies": {
"@firmachain/firma-js": "^0.2.47",
"child_process": "^1.0.2"
}
}
1 change: 1 addition & 0 deletions public/identity.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"profileInfos":[],"lastUpdatedTime":0}
2 changes: 2 additions & 0 deletions shellScripts/gitAdd.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
git add public/identity.json
2 changes: 2 additions & 0 deletions shellScripts/gitCommit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/bash
git commit -m "update: identity.json file has been updated"
2 changes: 2 additions & 0 deletions shellScripts/gitConfig.sample.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
git config --global user.name "your name"
git config --global user.email "your email"
2 changes: 2 additions & 0 deletions shellScripts/gitPull.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
git pull
2 changes: 2 additions & 0 deletions shellScripts/gitPush.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#!/bin/sh
git push -u origin master
12 changes: 12 additions & 0 deletions src/config.sample.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { FirmaConfig } from "@firmachain/firma-js";

export const FIRMACHAIN_CONFIG = FirmaConfig.MainNetConfig;
export const KEYBASE_URL = "https://keybase.io/_/api/1.0/user";
export const KEYBASE_PATH = "/lookup.json?fields=pictures&key_suffix=";
export const PUBLIC_PATH = `${__dirname}/../public/`;
export const IDENTITY_FILE_NAME = "identity.json";
export const GIT_CONFIG_FILE_NAME = "bash shellScripts/gitConfig.sh";
export const GIT_PULL_FILE_NAME = "bash shellScripts/gitPull.sh";
export const GIT_ADD_FILE_NAME = "bash shellScripts/gitAdd.sh";
export const GIT_COMMIT_FILE_NAME = "bash shellScripts/gitCommit.sh";
export const GIT_PUSH_FILE_NAME = "bash shellScripts/gitPush.sh";
75 changes: 75 additions & 0 deletions src/crawler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { getIdentityFile, writeIdentityFile } from "./utils/file";
import { IdentityFileInfo } from "./interfaces/common";
import {
gitPushProcess,
InitGitConfig
} from "./utils/gitUtil";
import {
compareIdentityInfo,
getImageUrlByIdentityInfos,
getValidatorList,
organizeIdentity
} from "./utils/crawlerUtil";

class CrawlerScheduler {
constructor() {
InitGitConfig();

this.Start();
}

private async Start() {
console.log("Start Crawler");
const validatorList = await getValidatorList();
if (validatorList.length === 0) {
console.log("validatorList length is zero");
this.Scheduler();
}

const identityInfos = organizeIdentity(validatorList);
if (identityInfos.length === 0) {
console.log("identityInfos length is zero");
this.Scheduler();
}

const imageUrlByIdentityInfos = await getImageUrlByIdentityInfos(identityInfos);
const newProfileJsonString = JSON.stringify(imageUrlByIdentityInfos);

const oldIdentityJsonString = getIdentityFile();
let oldProfileJsonString = "";

if (oldIdentityJsonString !== "") {
const oldProfileInfo: IdentityFileInfo = JSON.parse(oldIdentityJsonString);
oldProfileJsonString = JSON.stringify(oldProfileInfo.profileInfos);
}

const compareResult = compareIdentityInfo(newProfileJsonString, oldProfileJsonString);

console.log("End crawler");

if (!compareResult) {
const dateTime = new Date().getTime();
const fileInfo: IdentityFileInfo = {
profileInfos: imageUrlByIdentityInfos,
lastUpdatedTime: dateTime
};

writeIdentityFile(JSON.stringify(fileInfo));

gitPushProcess((isSuccess, comment) => {
console.log(comment);
this.Scheduler();
});
} else {
this.Scheduler();
}
}

private async Scheduler() {
setTimeout(async () => {
await this.Start();
}, 5000);
}
}

new CrawlerScheduler();
14 changes: 14 additions & 0 deletions src/interfaces/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export interface ShortDescription {
operatorAddress: string,
identity: string
};

export interface ValidatorProfileInfo {
operatorAddress: string,
url: string
};

export interface IdentityFileInfo {
profileInfos: ValidatorProfileInfo[],
lastUpdatedTime: number
};
16 changes: 16 additions & 0 deletions src/utils/axios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import axios, { AxiosRequestConfig } from 'axios';
import { KEYBASE_PATH, KEYBASE_URL } from '../config';

const axiosConfig: AxiosRequestConfig = { baseURL: KEYBASE_URL };
const axiosClient = axios.create(axiosConfig);

export const getAxios = async (identity: string, valOperAddr: string) => {
const response = await axiosClient.get(KEYBASE_PATH + identity);
try {
const url = response.data['them'][0]['pictures']['primary']['url'];
return url;
} catch (e) {
console.log(valOperAddr);
return "";
}
}
14 changes: 14 additions & 0 deletions src/utils/bashCmd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { exec } from "child_process";

export const executeCommand = (cmd: string, callback: (isSuccess: boolean) => void) => {
exec(cmd, (err, stdout, stderr) => {
if (err) {
console.log(stderr);
callback(false);
}

console.log(stdout);

callback(true);
});
}
75 changes: 75 additions & 0 deletions src/utils/crawlerUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { FirmaConfig, FirmaSDK, FirmaUtil, ValidatorDataType } from "@firmachain/firma-js";
import { ShortDescription, ValidatorProfileInfo } from "../interfaces/common";
import { getAxios } from "./axios";

export const getValidatorList = async () => {
try {
const firma = new FirmaSDK(FirmaConfig.MainNetConfig);
const validatorList = await firma.Staking.getValidatorList();

let dataList: ValidatorDataType[] = validatorList.dataList;
let nextKey: string = validatorList.pagination.next_key;

while (nextKey !== null) {
const nextValidatorList = await firma.Staking.getValidatorList(nextKey);
const nextDataList = nextValidatorList.dataList;
nextKey = nextValidatorList.pagination.next_key;

dataList.push(...nextDataList);
}

return dataList;
} catch (e) {
console.log(e);
return [];
}
}

export const organizeIdentity = (validatorList: ValidatorDataType[]) => {
let IdentityInfos: ShortDescription[] = [];

for (let i = 0; i < validatorList.length; i++) {
const currentValidator = validatorList[i];

try {
const valOperAddr = currentValidator.operator_address;
const identity = currentValidator.description.identity;

if (identity !== "") {
IdentityInfos.push({ operatorAddress: valOperAddr, identity: identity });
}
} catch (e) {
console.log(e);
console.log(`${currentValidator.operator_address} - Abnormalities in value <- Identity ->.`);
}
}

return IdentityInfos;
}

export const getImageUrlByIdentityInfos = async (identityInfos: ShortDescription[]) => {
let validatorProfileInfos: ValidatorProfileInfo[] = [];

for (let i = 0; i < identityInfos.length; i++) {
const currentInfo = identityInfos[i];
const imageUrl = await getAxios(currentInfo.identity, currentInfo.operatorAddress);

validatorProfileInfos.push({
operatorAddress: currentInfo.operatorAddress,
url: imageUrl
})
}

return validatorProfileInfos;
}

export const compareIdentityInfo = (newString: string, oldString: string) => {
const newFileHash = FirmaUtil.getHashFromString(newString);
const oldFileHash = FirmaUtil.getHashFromString(oldString);

if (newFileHash === oldFileHash) {
return true;
}

return false;
}
21 changes: 21 additions & 0 deletions src/utils/file.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@

import { IDENTITY_FILE_NAME, PUBLIC_PATH } from '../config';
import * as fs from 'fs';

export const writeIdentityFile = (jsonString: string) => {
try {
fs.writeFileSync(PUBLIC_PATH + IDENTITY_FILE_NAME, jsonString, 'utf-8');
console.log('[COMPLETED] write file');
} catch (e) {
console.log('[FAILED] write file');
}
}

export const getIdentityFile = () => {
try {
const identityInfo = fs.readFileSync(PUBLIC_PATH + IDENTITY_FILE_NAME, 'utf-8');
return identityInfo;
} catch (e) {
return "";
}
}
52 changes: 52 additions & 0 deletions src/utils/gitUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import {
GIT_ADD_FILE_NAME, GIT_COMMIT_FILE_NAME, GIT_CONFIG_FILE_NAME, GIT_PULL_FILE_NAME, GIT_PUSH_FILE_NAME
} from "../config";
import { executeCommand } from "./bashCmd";

export const InitGitConfig = () => {
executeCommand(GIT_CONFIG_FILE_NAME, (isSuccess) => {
if (isSuccess) {
console.log('[SUCCESS] GIT CONFIG SET UP');
}
return isSuccess;
});
};

export const gitPushProcess = (callback: (isSuccess: boolean, comment: string) => void) => {
executeCommand(GIT_PULL_FILE_NAME, (pullResult) => {
if (pullResult) {
console.log('[SUCCESS] GIT PULL');

executeCommand(GIT_ADD_FILE_NAME, (addResult) => {
if (addResult) {
console.log('[SUCCESS] GIT ADD FILE');

executeCommand(GIT_COMMIT_FILE_NAME, (commitResult) => {
if (commitResult) {
console.log('[SUCCESS] GIT COMMIT');

executeCommand(GIT_PUSH_FILE_NAME, (pushResult) => {
if (pushResult) {
console.log('[SUCCESS] GIT PUSH');
callback(pushResult, "process completed");
} else {
console.log('[FAILED] GIT PUSH');
callback(pushResult, "process failed");
}
});
} else {
console.log('[FAILED] GIT COMMIT');
callback(commitResult, "process failed");
}
});
} else {
console.log('[FAILED] GIT ADD FILE');
callback(addResult, "process failed");
}
});
} else {
console.log('[FAILED] GIT PULL');
callback(pullResult, "process failed");
}
});
};
18 changes: 18 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"strictPropertyInitialization": false,
"experimentalDecorators": true,
"target": "es5",
"module": "commonjs",
"baseUrl": "src",
"rootDir": "./src",
"outDir": "./dist",
"esModuleInterop": true,
"resolveJsonModule": true,
"lib": ["es6", "dom", "esnext.asynciterable"],
"downlevelIteration": true,
"strict": true
},
"include": ["src/**/*.ts", ".env"],
"exclude": ["node_modules", "test"]
}

0 comments on commit e2ff674

Please sign in to comment.