├── README.md ├── Scripts └── mine.js ├── Src ├── Addon │ ├── hash-creator.js │ ├── hash-creator.ts │ ├── sign.js │ └── sign.ts ├── classes │ ├── Blockchain │ │ ├── Block.js │ │ ├── Block.ts │ │ ├── Blockchain.js │ │ ├── Blockchain.ts │ │ ├── Transaction.js │ │ ├── Transaction.ts │ │ ├── TransactionMiner.js │ │ ├── TransactionMiner.ts │ │ ├── TransactionPool.js │ │ ├── TransactionPool.ts │ │ ├── Wallet.js │ │ └── Wallet.ts │ └── Network │ │ ├── Nodes.js │ │ ├── Nodes.ts │ │ ├── Root.js │ │ └── Root.ts ├── interfaces │ ├── Blockchain │ │ ├── _Block.js │ │ ├── _Block.ts │ │ ├── _Blockchain.js │ │ ├── _Blockchain.ts │ │ ├── _Transaction.js │ │ ├── _Transaction.ts │ │ ├── _TransactionMiner.js │ │ ├── _TransactionMiner.ts │ │ ├── _TransactionPool.js │ │ ├── _TransactionPool.ts │ │ ├── _Wallet.js │ │ └── _Wallet.ts │ └── Network │ │ ├── _Nodes.js │ │ ├── _Nodes.ts │ │ ├── _Root.js │ │ └── _Root.ts └── types │ ├── errors_interface.js │ ├── errors_interface.ts │ ├── inputMap_types.js │ └── inputMap_types.ts ├── config.js ├── config.ts ├── errors.txt ├── index.js ├── package-lock.json ├── package.json └── tsconfig.json /README.md: -------------------------------------------------------------------------------- 1 | # Blockchain-Server-JS 2 | A blockchain built using Node js/Go 3 | The blockchain was supposed to reach the commercial stage in collaboration with one of the programming groups, which was canceled. 4 | I decided to make the source public, so that if anyone wanted to use it. 5 | 6 | client-side source -> [Blockchain-client](https://github.com/hamidreza01/Blockchain-client) 7 | -------------------------------------------------------------------------------- /Scripts/mine.js: -------------------------------------------------------------------------------- 1 | const {Blockchain : BlockChain} = require("../Src/classes/Blockchain/Blockchain") 2 | const { style } = require("cls.js"); 3 | const cluster = require("cluster"); 4 | const numCPUs = 2; 5 | 6 | if (cluster.isPrimary) { 7 | console.log(`Primary ${process.pid} is running`); 8 | 9 | for (let i = 0; i < numCPUs; i++) { 10 | cluster.fork(); 11 | }; 12 | 13 | 14 | cluster.on("exit", (worker, code, signal) => { 15 | console.log(`worker ${worker.process.pid} died`); 16 | }); 17 | } else { 18 | console.log(`Worker ${process.pid} started`); 19 | const blockChain = new BlockChain(); 20 | blockChain.addBlock("initial"); 21 | let pt, nt, nb, td, average; 22 | const times = []; 23 | for (let i = 0; i < 10000; i++) { 24 | pt = blockChain.chain[blockChain.chain.length - 1].timestamp; 25 | blockChain.addBlock(`block${i}`); 26 | nb = blockChain.chain[blockChain.chain.length - 1]; 27 | nt = nb.timestamp; 28 | td = nt - pt; 29 | times.push(td); 30 | average = 31 | times.reduce((total, num) => { 32 | return total + num; 33 | }) / times.length; 34 | 35 | style({ 36 | text: `time to mine block : ${td}ms`, 37 | color: "blue", 38 | }); 39 | style({ 40 | text: `Difficulity : ${nb.difficulty}`, 41 | color: "red", 42 | }); 43 | 44 | style({ 45 | text: `average time : ${Math.floor(average)}ms`, 46 | color: "yellow", 47 | }); 48 | style({ 49 | text: `-----------------------`, 50 | color: "white", 51 | }) 52 | console.log(BlockChain.isValid(blockChain.chain)) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Src/Addon/hash-creator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | Object.defineProperty(exports, "__esModule", { value: true }); 26 | exports.hashCreator = void 0; 27 | const crypto = __importStar(require("crypto")); 28 | const hashCreator = (...data) => { 29 | const hash = crypto.createHash("sha256"); 30 | return hash 31 | .update(data 32 | .sort() 33 | .map((x) => { 34 | return JSON.stringify(x); 35 | }) 36 | .join(" ")) 37 | .digest("hex"); 38 | }; 39 | exports.hashCreator = hashCreator; 40 | -------------------------------------------------------------------------------- /Src/Addon/hash-creator.ts: -------------------------------------------------------------------------------- 1 | import * as crypto from "crypto"; 2 | export const hashCreator = (...data: Array): string => { 3 | const hash = crypto.createHash("sha256"); 4 | return hash 5 | .update( 6 | data 7 | .sort() 8 | .map((x) => { 9 | return JSON.stringify(x); 10 | }) 11 | .join(" ") 12 | ) 13 | .digest("hex"); 14 | }; 15 | -------------------------------------------------------------------------------- /Src/Addon/sign.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.recoveryKeyPair = exports.verify = exports.ec = void 0; 7 | const elliptic_1 = __importDefault(require("elliptic")); 8 | const hash_creator_1 = require("./hash-creator"); 9 | exports.ec = new elliptic_1.default.ec("ed25519"); 10 | const verify = (data, sign, publicKey) => { 11 | const vrf = exports.ec.keyFromPublic(publicKey, "hex"); 12 | try { 13 | return vrf.verify((0, hash_creator_1.hashCreator)(JSON.stringify(data)), sign); 14 | } 15 | catch (error) { 16 | return false; 17 | } 18 | }; 19 | exports.verify = verify; 20 | const recoveryKeyPair = (privateKey, publicKey) => { 21 | return exports.ec.keyPair({ 22 | "priv": Buffer.from(privateKey, 'base64').toString(), 23 | "pubEnc": publicKey, 24 | }); 25 | }; 26 | exports.recoveryKeyPair = recoveryKeyPair; 27 | -------------------------------------------------------------------------------- /Src/Addon/sign.ts: -------------------------------------------------------------------------------- 1 | import elliptic, { SignatureInput } from "elliptic"; 2 | import { hashCreator } from "./hash-creator"; 3 | 4 | export const ec = new elliptic.ec("ed25519"); 5 | export const verify = ( 6 | data: any, 7 | sign: SignatureInput, 8 | publicKey: string 9 | ): boolean => { 10 | const vrf = ec.keyFromPublic(publicKey, "hex"); 11 | try { 12 | return vrf.verify(hashCreator(JSON.stringify(data)), sign); 13 | } catch (error) { 14 | return false; 15 | } 16 | }; 17 | export const recoveryKeyPair = (privateKey: string, publicKey : string) => { 18 | return ec.keyPair({ 19 | "priv" : Buffer.from(privateKey,'base64').toString() as any, 20 | "pubEnc" : publicKey, 21 | }) 22 | } 23 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/Block.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.Block = void 0; 7 | const config_1 = require("../../../config"); 8 | const hash_creator_1 = require("../../Addon/hash-creator"); 9 | const hex_to_bin_1 = __importDefault(require("hex-to-bin")); 10 | class Block { 11 | timestamp; 12 | data; 13 | hash; 14 | lastHash; 15 | nonce; 16 | difficulty; 17 | constructor(timestamp, data, hash, lastHash, nonce, difficulty) { 18 | this.timestamp = timestamp; 19 | this.data = data; 20 | this.hash = hash; 21 | this.lastHash = lastHash; 22 | this.nonce = nonce; 23 | this.difficulty = difficulty; 24 | } 25 | static genesis() { 26 | return config_1.config.GENESIS_DATA; 27 | } 28 | static mineBlock(lastBlock, data) { 29 | const { hash: lastHash } = lastBlock; 30 | let difficulty = lastBlock.difficulty; 31 | let nonce = 0; 32 | let hash, timestamp; 33 | do { 34 | nonce++; 35 | timestamp = Date.now(); 36 | difficulty = Block.adJustDifficulty(lastBlock, timestamp); 37 | hash = (0, hash_creator_1.hashCreator)(lastHash, nonce.toString(), timestamp.toString(), JSON.stringify(data), difficulty.toString()); 38 | } while ((0, hex_to_bin_1.default)(hash).slice(0, difficulty) !== "0".repeat(difficulty)); 39 | { 40 | return new Block(timestamp, data, hash, lastHash, nonce, difficulty); 41 | } 42 | } 43 | static adJustDifficulty(lastBlock, timestamp) { 44 | if (lastBlock.difficulty < 1) 45 | return 1; 46 | if (timestamp - lastBlock.timestamp > config_1.config.MINE_RATE) 47 | return lastBlock.difficulty - 1; 48 | return lastBlock.difficulty + 1; 49 | } 50 | } 51 | exports.Block = Block; 52 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/Block.ts: -------------------------------------------------------------------------------- 1 | import { config } from "../../../config"; 2 | import { hashCreator } from "../../Addon/hash-creator"; 3 | import { _Block } from "../../interfaces/Blockchain/_Block"; 4 | 5 | import hexToBin from "hex-to-bin"; 6 | import { _Transaction } from "../../interfaces/Blockchain/_Transaction"; 7 | 8 | export class Block implements _Block { 9 | constructor( 10 | public timestamp: number, 11 | public data: {transaction ?: [_Transaction]}, 12 | public hash: string, 13 | public lastHash: string, 14 | public nonce: number, 15 | public difficulty: number 16 | ) {} 17 | static genesis(): _Block { 18 | return config.GENESIS_DATA; 19 | } 20 | static mineBlock(lastBlock: _Block, data: {transaction ?: [_Transaction]}): _Block { 21 | const { hash: lastHash } = lastBlock; 22 | let difficulty = lastBlock.difficulty; 23 | let nonce = 0; 24 | let hash: string, timestamp: number; 25 | do { 26 | nonce++; 27 | timestamp = Date.now(); 28 | difficulty = Block.adJustDifficulty(lastBlock, timestamp); 29 | hash = hashCreator( 30 | lastHash, 31 | nonce.toString(), 32 | timestamp.toString(), 33 | JSON.stringify(data), 34 | difficulty.toString() 35 | ); 36 | } while (hexToBin(hash).slice(0, difficulty) !== "0".repeat(difficulty)); 37 | { 38 | return new Block(timestamp, data, hash, lastHash, nonce, difficulty); 39 | } 40 | } 41 | static adJustDifficulty(lastBlock: _Block, timestamp: number) { 42 | if (lastBlock.difficulty < 1) return 1; 43 | if (timestamp - lastBlock.timestamp > config.MINE_RATE) 44 | return lastBlock.difficulty - 1; 45 | return lastBlock.difficulty + 1; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/Blockchain.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.Blockchain = void 0; 4 | const hash_creator_1 = require("../../Addon/hash-creator"); 5 | const Block_1 = require("./Block"); 6 | const config_1 = require("../../../config"); 7 | const Transaction_1 = require("./Transaction"); 8 | const Wallet_1 = require("./Wallet"); 9 | class Blockchain { 10 | chain = [Block_1.Block.genesis()]; 11 | addBlock(data) { 12 | const block = Block_1.Block.mineBlock(this.chain[this.chain.length - 1], data); 13 | this.chain.push(block); 14 | } 15 | static isValid(chain) { 16 | if (JSON.stringify(chain[0]) !== JSON.stringify(Block_1.Block.genesis())) 17 | return false; 18 | for (let i = 1; i < chain.length; i++) { 19 | if (chain[i].hash !== 20 | (0, hash_creator_1.hashCreator)(chain[i].lastHash, JSON.stringify(chain[i].data), chain[i].nonce.toString(), chain[i].difficulty.toString(), chain[i].timestamp.toString())) { 21 | return false; 22 | } 23 | if (chain[i].lastHash !== chain[i - 1].hash) { 24 | return false; 25 | } 26 | if (Math.abs(chain[i - 1].difficulty - chain[i].difficulty) > 1) { 27 | return false; 28 | } 29 | } 30 | return true; 31 | } 32 | replaceChain(chain) { 33 | if (chain.length < this.chain.length) { 34 | return { message: "chain is short", code: 101 }; 35 | } 36 | if (!Blockchain.isValid(chain)) { 37 | return { message: "chain is not valid", code: 102 }; 38 | } 39 | this.chain = chain; 40 | return true; 41 | } 42 | validTransactionData(chain) { 43 | for (let i = 1; i < chain?.length; i++) { 44 | if (chain[i]?.data?.transaction?.length < 1) 45 | return { message: "chain data is empty", code: 120 }; 46 | for (let transaction of chain[i]?.data?.transaction) { 47 | let rewardNumber = 0; 48 | if (transaction?.inputMap?.address === config_1.config.REWARD_TRANSACTION.address) { 49 | rewardNumber++; 50 | if (rewardNumber > 1) { 51 | return { 52 | message: "reward transaction length is ivalid", 53 | code: 122, 54 | }; 55 | } 56 | if (Object.values(transaction.outputMap).reduce((all, val) => (all + val)) > config_1.config.REWARD) { 57 | return { message: "reward transaction is invalid", code: 121 }; 58 | } 59 | } 60 | else { 61 | let transactionResualt = Transaction_1.Transaction.isValid(transaction); 62 | if (transactionResualt !== true) { 63 | return transactionResualt; 64 | } 65 | else { 66 | const trueValue = Wallet_1.Wallet.calculateBalance(this.chain, transaction.inputMap.address); 67 | if (trueValue !== transaction.inputMap.amount) { 68 | return { message: "transaction amount is invalid", code: 123 }; 69 | } 70 | } 71 | } 72 | } 73 | } 74 | return true; 75 | } 76 | } 77 | exports.Blockchain = Blockchain; 78 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/Blockchain.ts: -------------------------------------------------------------------------------- 1 | import { hashCreator } from "../../Addon/hash-creator"; 2 | import { _Blockchain } from "../../interfaces/Blockchain/_Blockchain"; 3 | import { _Errors } from "../../types/errors_interface"; 4 | import { _Block } from "../../interfaces/Blockchain/_Block"; 5 | import { Block } from "./Block"; 6 | import { _Transaction } from "../../interfaces/Blockchain/_Transaction"; 7 | import { config } from "../../../config"; 8 | import { Transaction } from "./Transaction"; 9 | import { Wallet } from "./Wallet"; 10 | export class Blockchain implements _Blockchain { 11 | chain = [Block.genesis()]; 12 | 13 | addBlock(data: { transaction: [_Transaction] }): void { 14 | const block = Block.mineBlock(this.chain[this.chain.length - 1], data); 15 | this.chain.push(block); 16 | } 17 | 18 | static isValid(chain: Array<_Block>): boolean { 19 | if (JSON.stringify(chain[0]) !== JSON.stringify(Block.genesis())) 20 | return false; 21 | for (let i = 1; i < chain.length; i++) { 22 | if ( 23 | chain[i].hash !== 24 | hashCreator( 25 | chain[i].lastHash, 26 | JSON.stringify(chain[i].data), 27 | chain[i].nonce.toString(), 28 | chain[i].difficulty.toString(), 29 | chain[i].timestamp.toString() 30 | ) 31 | ) { 32 | return false; 33 | } 34 | 35 | if (chain[i].lastHash !== chain[i - 1].hash) { 36 | return false; 37 | } 38 | if (Math.abs(chain[i - 1].difficulty - chain[i].difficulty) > 1) { 39 | return false; 40 | } 41 | } 42 | return true; 43 | } 44 | replaceChain(chain: Array<_Block>): _Errors | boolean { 45 | if (chain.length < this.chain.length) { 46 | return { message: "chain is short", code: 101 }; 47 | } 48 | if (!Blockchain.isValid(chain)) { 49 | return { message: "chain is not valid", code: 102 }; 50 | } 51 | this.chain = chain; 52 | return true; 53 | } 54 | validTransactionData(chain: Array<_Block>): boolean | _Errors { 55 | for (let i = 1; i < chain?.length; i++) { 56 | if (chain[i]?.data?.transaction?.length! < 1) 57 | return { message: "chain data is empty", code: 120 }; 58 | for (let transaction of chain[i]?.data?.transaction!) { 59 | let rewardNumber = 0; 60 | if ( 61 | transaction?.inputMap?.address === config.REWARD_TRANSACTION.address 62 | ) { 63 | rewardNumber++; 64 | if (rewardNumber > 1) { 65 | return { 66 | message: "reward transaction length is ivalid", 67 | code: 122, 68 | }; 69 | } 70 | if ( 71 | (Object.values(transaction.outputMap).reduce( 72 | (all, val) => ((all as any) + val) as any 73 | ) as number) > config.REWARD 74 | ) { 75 | return { message: "reward transaction is invalid", code: 121 }; 76 | } 77 | } else { 78 | let transactionResualt = Transaction.isValid(transaction); 79 | if (transactionResualt !== true) { 80 | return transactionResualt; 81 | } else { 82 | const trueValue = Wallet.calculateBalance( 83 | this.chain, 84 | transaction.inputMap.address 85 | ); 86 | if (trueValue !== transaction.inputMap.amount) { 87 | return { message: "transaction amount is invalid", code: 123 }; 88 | } 89 | } 90 | } 91 | } 92 | } 93 | return true; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/Transaction.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.Transaction = void 0; 7 | const uniqid_1 = __importDefault(require("uniqid")); 8 | const sign_1 = require("../../Addon/sign"); 9 | const config_1 = require("../../../config"); 10 | class Transaction { 11 | id = (0, uniqid_1.default)(); 12 | outputMap = {}; 13 | inputMap = { 14 | timestamp: 0, 15 | address: "", 16 | amount: 0, 17 | signature: { s: "", r: "" }, 18 | }; 19 | constructor(senderWallet, amount, recpient, inputMap, outputMap) { 20 | (this.outputMap = outputMap || this.outputMapCreator(senderWallet, amount, recpient)), 21 | (this.inputMap = inputMap || this.inputMapCreator(senderWallet, this.outputMap)); 22 | } 23 | inputMapCreator(senderWallet, outputMap) { 24 | return { 25 | timestamp: Date.now(), 26 | address: senderWallet.publicKey, 27 | amount: senderWallet.balance, 28 | signature: senderWallet.sign(outputMap), 29 | }; 30 | } 31 | outputMapCreator(senderWallet, amount, recipient) { 32 | let outputMap = {}; 33 | outputMap[senderWallet.publicKey] = senderWallet.balance - amount; 34 | outputMap[recipient] = amount; 35 | return outputMap; 36 | } 37 | update(recpient, amount, senderWallet) { 38 | if (this.outputMap[senderWallet.publicKey] < amount) { 39 | return { message: "amount exceeds balance", code: 112 }; 40 | } 41 | if (this.outputMap[recpient]) { 42 | this.outputMap[recpient] += amount; 43 | } 44 | else { 45 | this.outputMap[recpient] = amount; 46 | } 47 | this.inputMap = this.inputMapCreator(senderWallet, this.outputMap); 48 | } 49 | static isValid(transaction) { 50 | let total = Object.values(transaction.outputMap).reduce((all, val) => { 51 | return all + val; 52 | }); 53 | if (total !== transaction.inputMap.amount) { 54 | return { 55 | message: `invalid transaction from ${transaction.inputMap.address}`, 56 | code: 111, 57 | }; 58 | } 59 | if (!(0, sign_1.verify)(transaction.outputMap, transaction.inputMap.signature, transaction.inputMap.address)) { 60 | return { 61 | message: `invalid transaction from ${transaction.inputMap.address}`, 62 | code: 112, 63 | }; 64 | } 65 | return true; 66 | } 67 | static reward(minerWallet) { 68 | return new Transaction(minerWallet, 0, minerWallet.publicKey, config_1.config.REWARD_TRANSACTION, { [minerWallet.publicKey]: config_1.config.REWARD }); 69 | } 70 | } 71 | exports.Transaction = Transaction; 72 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/Transaction.ts: -------------------------------------------------------------------------------- 1 | import { _Transaction } from "../../interfaces/Blockchain/_Transaction"; 2 | import { _Wallet } from "../../interfaces/Blockchain/_Wallet"; 3 | import uniqid from "uniqid"; 4 | import { _Errors } from "../../types/errors_interface"; 5 | import { verify } from "../../Addon/sign"; 6 | import { inputMap_type } from "../../types/inputMap_types"; 7 | import { config } from "../../../config"; 8 | export class Transaction implements _Transaction { 9 | id: string = uniqid(); 10 | public outputMap: any = {}; 11 | public inputMap: inputMap_type = { 12 | timestamp: 0, 13 | address: "", 14 | amount: 0, 15 | signature: { s: "", r: "" }, 16 | }; 17 | constructor(senderWallet: _Wallet, amount: number, recpient: string, inputMap?: inputMap_type, outputMap?: {}) { 18 | (this.outputMap = outputMap || this.outputMapCreator(senderWallet, amount, recpient)), 19 | (this.inputMap = inputMap || this.inputMapCreator(senderWallet, this.outputMap)); 20 | } 21 | inputMapCreator(senderWallet: _Wallet, outputMap: {}): inputMap_type { 22 | return { 23 | timestamp: Date.now(), 24 | address: senderWallet.publicKey, 25 | amount: senderWallet.balance, 26 | signature: senderWallet.sign(outputMap), 27 | }; 28 | } 29 | outputMapCreator( 30 | senderWallet: _Wallet, 31 | amount: number, 32 | recipient: string 33 | ): {} { 34 | let outputMap: any = {}; 35 | outputMap[senderWallet.publicKey] = senderWallet.balance - amount; 36 | outputMap[recipient] = amount; 37 | return outputMap; 38 | } 39 | update( 40 | recpient: string, 41 | amount: number, 42 | senderWallet: _Wallet 43 | ): void | _Errors { 44 | if (this.outputMap[senderWallet.publicKey] < amount) { 45 | return { message: "amount exceeds balance", code: 112 }; 46 | } 47 | if(this.outputMap[recpient]){ 48 | this.outputMap[recpient] += amount 49 | }else{ 50 | this.outputMap[recpient] = amount; 51 | } 52 | this.inputMap = this.inputMapCreator(senderWallet,this.outputMap) 53 | } 54 | static isValid(transaction: _Transaction): _Errors | boolean { 55 | let total = Object.values(transaction.outputMap).reduce((all, val: any) => { 56 | return (all as number) + val; 57 | }); 58 | if (total !== transaction.inputMap.amount) { 59 | return { 60 | message: `invalid transaction from ${transaction.inputMap.address}`, 61 | code: 111, 62 | }; 63 | } 64 | if ( 65 | !verify( 66 | transaction.outputMap, 67 | transaction.inputMap.signature, 68 | transaction.inputMap.address 69 | ) 70 | ) { 71 | return { 72 | message: `invalid transaction from ${transaction.inputMap.address}`, 73 | code: 112, 74 | }; 75 | } 76 | return true; 77 | } 78 | static reward(minerWallet: _Wallet): _Transaction { 79 | return new Transaction( 80 | minerWallet, 81 | 0, 82 | minerWallet.publicKey, 83 | config.REWARD_TRANSACTION as any, 84 | {[minerWallet.publicKey]: config.REWARD} 85 | ); 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/TransactionMiner.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.TransactionMiner = void 0; 4 | const Transaction_1 = require("./Transaction"); 5 | class TransactionMiner { 6 | transactionPool; 7 | blockchain; 8 | wallet; 9 | nodes; 10 | constructor(transactionPool, blockchain, wallet, nodes) { 11 | this.transactionPool = transactionPool; 12 | this.blockchain = blockchain; 13 | this.wallet = wallet; 14 | this.nodes = nodes; 15 | } 16 | mineTransaction() { 17 | return new Promise((res) => { 18 | const transactions = [Transaction_1.Transaction.reward(this.wallet), ...Object.values(this.transactionPool.transactionMap)]; 19 | this.blockchain.addBlock({ transaction: transactions }); 20 | this.nodes.broadcast("chain", this.blockchain.chain); 21 | this.transactionPool.clear(); 22 | res(); 23 | }); 24 | } 25 | } 26 | exports.TransactionMiner = TransactionMiner; 27 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/TransactionMiner.ts: -------------------------------------------------------------------------------- 1 | import { _Nodes } from "../../interfaces/Network/_Nodes"; 2 | import { _Block } from "../../interfaces/Blockchain/_Block"; 3 | import { _Wallet } from "../../interfaces/Blockchain/_Wallet"; 4 | import { _Blockchain } from "../../interfaces/Blockchain/_Blockchain"; 5 | import { Transaction } from "./Transaction"; 6 | import { _TransactionPool } from "../../interfaces/Blockchain/_TransactionPool"; 7 | import { _Transaction } from "../../interfaces/Blockchain/_Transaction"; 8 | import { _TransactionMiner } from "../../interfaces/Blockchain/_TransactionMiner"; 9 | export class TransactionMiner implements _TransactionMiner{ 10 | constructor(private transactionPool : _TransactionPool, private blockchain : _Blockchain, private wallet : _Wallet, private nodes : _Nodes ){ 11 | } 12 | mineTransaction() : Promise { 13 | return new Promise((res)=>{ 14 | const transactions =[Transaction.reward(this.wallet),...Object.values(this.transactionPool.transactionMap)]; 15 | this.blockchain.addBlock({transaction : transactions as any}); 16 | this.nodes.broadcast("chain",this.blockchain.chain); 17 | this.transactionPool.clear(); 18 | res() 19 | }) 20 | } 21 | } -------------------------------------------------------------------------------- /Src/classes/Blockchain/TransactionPool.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.TransactionPool = void 0; 4 | class TransactionPool { 5 | transactionMap = {}; 6 | constructor() { 7 | } 8 | add(transaction) { 9 | this.transactionMap[transaction.id] = transaction; 10 | } 11 | isHave(wallet) { 12 | let val = Object.values(this.transactionMap); 13 | return val.find(x => { 14 | return x.inputMap.address === wallet.publicKey; 15 | }); 16 | } 17 | clear() { 18 | this.transactionMap = {}; 19 | } 20 | clearBlockchainTransactions(chain) { 21 | for (let i = 1; i < chain.length; i++) { 22 | const block = chain[i]; 23 | for (let j = 1; j < block.data.transaction.length; j++) { 24 | const tx = block.data.transaction[j]; 25 | delete this.transactionMap[tx.id]; 26 | } 27 | } 28 | } 29 | } 30 | exports.TransactionPool = TransactionPool; 31 | ; 32 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/TransactionPool.ts: -------------------------------------------------------------------------------- 1 | import { _Transaction } from "../../interfaces/Blockchain/_Transaction"; 2 | import { _TransactionPool } from "../../interfaces/Blockchain/_TransactionPool"; 3 | import { _Wallet } from "../../interfaces/Blockchain/_Wallet"; 4 | import { _Errors } from "../../types/errors_interface"; 5 | import { Transaction } from "./Transaction"; 6 | import {_Block} from "../../interfaces/Blockchain/_Block"; 7 | export class TransactionPool implements _TransactionPool { 8 | transactionMap : any = {}; 9 | constructor(){ 10 | } 11 | add(transaction : _Transaction) : void | _Errors { 12 | this.transactionMap[transaction.id] = transaction; 13 | } 14 | isHave(wallet : _Wallet) : _Transaction | undefined { 15 | let val = Object.values(this.transactionMap) as Array<_Transaction> 16 | return val.find(x=>{ 17 | return x.inputMap.address === wallet.publicKey 18 | }); 19 | } 20 | clear(){ 21 | this.transactionMap = {} 22 | } 23 | clearBlockchainTransactions(chain : Array<_Block>) : void { 24 | for(let i = 1 ; i < chain.length ; i++){ 25 | const block = chain[i]; 26 | for(let j = 1 ; j < block.data.transaction!.length ; j++){ 27 | const tx = block.data.transaction![j]; 28 | delete this.transactionMap[tx.id]; 29 | } 30 | } 31 | } 32 | }; -------------------------------------------------------------------------------- /Src/classes/Blockchain/Wallet.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.Wallet = void 0; 4 | const sign_1 = require("../../Addon/sign"); 5 | const config_1 = require("../../../config"); 6 | const hash_creator_1 = require("../../Addon/hash-creator"); 7 | const Transaction_1 = require("./Transaction"); 8 | class Wallet { 9 | balance = config_1.config.DEFUALT_BALANCE; 10 | keyPair = sign_1.ec.genKeyPair(); 11 | publicKey = this.keyPair.getPublic().encode("hex"); 12 | privateKey = Buffer.from(JSON.stringify(this.keyPair.getPrivate()).replace(/\"/g, '')).toString("base64"); 13 | // privateKey: string = this.keyPair.getPrivate(); 14 | sign(data) { 15 | return this.keyPair.sign((0, hash_creator_1.hashCreator)(JSON.stringify(data))); 16 | } 17 | createTransaction(recipient, amount, chain) { 18 | this.balance = Wallet.calculateBalance(chain, this.publicKey); 19 | // console.log(amount , this.balance) 20 | if (amount > this.balance) { 21 | return { message: "amount exceeds balance", code: 112 }; 22 | } 23 | return new Transaction_1.Transaction(this, amount, recipient); 24 | } 25 | static calculateBalance(chain, address) { 26 | let value = 0; 27 | let hasTransaction = false; 28 | for (let i = chain?.length - 1; i > 0; i--) { 29 | for (let transaction of Object.values(chain[i]?.data?.transaction)) { 30 | if (transaction?.inputMap?.address === address) { 31 | hasTransaction = true; 32 | // break; 33 | } 34 | let outputValue; 35 | try { 36 | outputValue = transaction?.outputMap[address]; 37 | } 38 | catch (error) { 39 | outputValue = 0; 40 | } 41 | if (outputValue) { 42 | value += outputValue; 43 | } 44 | } 45 | if (hasTransaction) { 46 | break; 47 | } 48 | } 49 | return value; 50 | } 51 | } 52 | exports.Wallet = Wallet; 53 | -------------------------------------------------------------------------------- /Src/classes/Blockchain/Wallet.ts: -------------------------------------------------------------------------------- 1 | import { _Wallet } from "../../interfaces/Blockchain/_Wallet"; 2 | import { ec } from "../../Addon/sign"; 3 | import { config } from "../../../config"; 4 | import { hashCreator } from "../../Addon/hash-creator"; 5 | import { _Errors } from "../../types/errors_interface"; 6 | import { _Transaction } from "../../interfaces/Blockchain/_Transaction"; 7 | import { Transaction } from "./Transaction"; 8 | import { _Block } from "../../interfaces/Blockchain/_Block"; 9 | 10 | export class Wallet implements _Wallet { 11 | balance: number = config.DEFUALT_BALANCE; 12 | keyPair: any = ec.genKeyPair(); 13 | publicKey: string = this.keyPair.getPublic().encode("hex"); 14 | privateKey: string = Buffer.from(JSON.stringify(this.keyPair.getPrivate()).replace(/\"/g,'')).toString("base64"); 15 | // privateKey: string = this.keyPair.getPrivate(); 16 | sign(data: any): string { 17 | return this.keyPair.sign(hashCreator(JSON.stringify(data))); 18 | } 19 | createTransaction( 20 | recipient: string, 21 | amount: number, 22 | chain: Array<_Block> 23 | ): _Errors | _Transaction { 24 | this.balance = Wallet.calculateBalance(chain, this.publicKey)!; 25 | // console.log(amount , this.balance) 26 | if (amount > this.balance) { 27 | return { message: "amount exceeds balance", code: 112 }; 28 | } 29 | return new Transaction(this, amount, recipient); 30 | } 31 | static calculateBalance(chain: Array<_Block>, address: string) { 32 | let value = 0; 33 | let hasTransaction = false; 34 | for (let i = chain?.length - 1; i > 0; i--) { 35 | for (let transaction of Object.values(chain[i]?.data?.transaction!)) { 36 | if(transaction?.inputMap?.address === address){ 37 | hasTransaction = true; 38 | // break; 39 | } 40 | let outputValue; 41 | try { 42 | outputValue = transaction?.outputMap[address]; 43 | } catch (error) { 44 | outputValue = 0; 45 | } 46 | if (outputValue) { 47 | value += outputValue; 48 | } 49 | 50 | } 51 | if (hasTransaction) { 52 | break; 53 | } 54 | } 55 | return value; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Src/classes/Network/Nodes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.Nodes = void 0; 7 | const express_1 = __importDefault(require("express")); 8 | const axios_1 = __importDefault(require("axios")); 9 | class Nodes { 10 | port; 11 | list = [""]; 12 | app = (0, express_1.default)(); 13 | blockChain; 14 | constructor(port) { 15 | this.port = port; 16 | } 17 | start() { 18 | this.app.use(express_1.default.json()); 19 | this.app.listen(this.port); 20 | } 21 | async broadcast(name, data) { 22 | for (let i = 0; i < this.list.length; i++) { 23 | try { 24 | await axios_1.default.post(`http://${this.list[i]}/${name}`, data); 25 | console.log(`success send ${this.list[i]} with ${name} channel`); 26 | } 27 | catch (error) { 28 | console.log(`Error brodcast to ${this.list[i]} with ${name} channel`); 29 | } 30 | } 31 | } 32 | bet(name, callback) { 33 | this.app.use(express_1.default.json()); 34 | this.app.post("/" + name, (req, res) => { 35 | callback(req.body); 36 | res.send("ok"); 37 | }); 38 | } 39 | } 40 | exports.Nodes = Nodes; 41 | -------------------------------------------------------------------------------- /Src/classes/Network/Nodes.ts: -------------------------------------------------------------------------------- 1 | import express from "express"; 2 | import { _Block } from "../../interfaces/Blockchain/_Block"; 3 | import { _Blockchain } from "../../interfaces/Blockchain/_Blockchain"; 4 | import axios from "axios"; 5 | import { _Nodes } from "../../interfaces/Network/_Nodes"; 6 | export class Nodes implements _Nodes { 7 | list: Array = [""]; 8 | private app = express(); 9 | private blockChain: any; 10 | constructor(private port: number) {} 11 | start(): void { 12 | this.app.use(express.json()); 13 | this.app.listen(this.port); 14 | } 15 | async broadcast(name: string, data: any): Promise { 16 | for (let i = 0; i < this.list.length; i++) { 17 | try { 18 | await axios.post(`http://${this.list[i]}/${name}`, data); 19 | console.log(`success send ${this.list[i]} with ${name} channel`); 20 | } catch (error) { 21 | console.log(`Error brodcast to ${this.list[i]} with ${name} channel`); 22 | } 23 | } 24 | } 25 | bet(name: string, callback: Function): void { 26 | this.app.use(express.json()); 27 | this.app.post("/" + name, (req, res) => { 28 | callback(req.body) 29 | res.send("ok"); 30 | }); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Src/classes/Network/Root.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __importDefault = (this && this.__importDefault) || function (mod) { 3 | return (mod && mod.__esModule) ? mod : { "default": mod }; 4 | }; 5 | Object.defineProperty(exports, "__esModule", { value: true }); 6 | exports.Root = void 0; 7 | const config_1 = require("../../../config"); 8 | const net_1 = __importDefault(require("net")); 9 | class Root { 10 | port; 11 | client; 12 | constructor(port) { 13 | this.port = port; 14 | this.client = net_1.default.createConnection({ 15 | port: config_1.config.ROOT_PORT, 16 | host: config_1.config.ROOT_URL, 17 | localPort: port, 18 | }); 19 | } 20 | classData = [ 21 | { 22 | betName: "genesis", 23 | callBack: () => { 24 | console.log('oops, im genesis'); 25 | }, 26 | }, 27 | ]; 28 | start() { 29 | this.client.on("data", (data) => { 30 | console.log(data.toString()); 31 | try { 32 | data = JSON.parse(data.toString()); 33 | } 34 | catch (error) { 35 | console.log(error); 36 | } 37 | let better = this.classData.find((x) => { 38 | return x.betName === data.action; 39 | }); 40 | if (better) { 41 | better.callBack(data.data ? data.data : undefined); 42 | } 43 | }); 44 | return new Promise((res, rej) => { 45 | this.client.on("connect", () => { 46 | res(true); 47 | }); 48 | this.client.on("timeout", () => { 49 | rej({ message: "connect to the root server of timeout", code: 251 }); 50 | }); 51 | this.client.on("error", () => { 52 | rej({ message: "error connecting to the root server", code: 250 }); 53 | }); 54 | }); 55 | } 56 | addMe() { 57 | this.client.write(JSON.stringify({ action: "addMe" })); 58 | this.client.on("timeout", () => { 59 | return { message: "connect to the root server of timeout", code: 251 }; 60 | }); 61 | this.client.on("error", () => { 62 | return { message: "error connecting to the root server", code: 250 }; 63 | }); 64 | } 65 | giveData(chain, nodeList) { 66 | this.client.write(JSON.stringify({ action: "giveMeData", data: { chain, nodeList } })); 67 | this.client.on("timeout", () => { 68 | return { message: "connect to the root server of timeout", code: 251 }; 69 | }); 70 | this.client.on("error", () => { 71 | return { message: "error connecting to the root server", code: 250 }; 72 | }); 73 | } 74 | bet(betName, callBack) { 75 | this.classData.push({ betName, callBack }); 76 | } 77 | } 78 | exports.Root = Root; 79 | -------------------------------------------------------------------------------- /Src/classes/Network/Root.ts: -------------------------------------------------------------------------------- 1 | import { _Root } from "../../interfaces/Network/_Root"; 2 | import { _Errors } from "../../types/errors_interface"; 3 | import { config } from "../../../config"; 4 | import net from "net"; 5 | import { _Block } from "../../interfaces/Blockchain/_Block"; 6 | export class Root implements _Root { 7 | private client: any; 8 | constructor(private port: number) { 9 | this.client = net.createConnection({ 10 | port: config.ROOT_PORT, 11 | host: config.ROOT_URL, 12 | localPort: port, 13 | }); 14 | } 15 | private classData: Array<{ betName: string; callBack: Function }> = [ 16 | { 17 | betName: "genesis", 18 | callBack: () => { 19 | console.log('oops, im genesis') 20 | }, 21 | }, 22 | ]; 23 | start(): Promise<_Errors | boolean> { 24 | this.client.on("data", (data: any) => { 25 | console.log(data.toString()); 26 | try { 27 | data = JSON.parse(data.toString()); 28 | } catch (error) { 29 | console.log(error); 30 | } 31 | let better = this.classData.find((x) => { 32 | return x.betName === data.action; 33 | }); 34 | if (better) { 35 | better.callBack(data.data ? data.data : undefined); 36 | } 37 | }); 38 | return new Promise((res, rej) => { 39 | this.client.on("connect", () => { 40 | res(true); 41 | }); 42 | this.client.on("timeout", () => { 43 | rej({ message: "connect to the root server of timeout", code: 251 }); 44 | }); 45 | this.client.on("error", () => { 46 | rej({ message: "error connecting to the root server", code: 250 }); 47 | }); 48 | }); 49 | } 50 | addMe(): void | _Errors { 51 | this.client.write(JSON.stringify({ action: "addMe" })); 52 | this.client.on("timeout", () => { 53 | return { message: "connect to the root server of timeout", code: 251 }; 54 | }); 55 | this.client.on("error", () => { 56 | return { message: "error connecting to the root server", code: 250 }; 57 | }); 58 | } 59 | giveData(chain: Array<_Block>, nodeList: Array): void | _Errors { 60 | this.client.write( 61 | JSON.stringify({ action: "giveMeData", data: { chain, nodeList } }) 62 | ); 63 | this.client.on("timeout", () => { 64 | return { message: "connect to the root server of timeout", code: 251 }; 65 | }); 66 | this.client.on("error", () => { 67 | return { message: "error connecting to the root server", code: 250 }; 68 | }); 69 | } 70 | bet(betName: string, callBack: Function): void { 71 | this.classData.push({ betName, callBack }); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_Block.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_Block.ts: -------------------------------------------------------------------------------- 1 | import { _Transaction } from "./_Transaction"; 2 | 3 | export interface _Block { 4 | timestamp: number; 5 | data: {transaction ?: [_Transaction]}; 6 | hash: string; 7 | lastHash: string; 8 | nonce: number; 9 | difficulty: number; 10 | } 11 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_Blockchain.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_Blockchain.ts: -------------------------------------------------------------------------------- 1 | import { _Block } from "./_Block"; 2 | import { _Errors } from "../../types/errors_interface"; 3 | import { _Transaction } from "./_Transaction"; 4 | export interface _Blockchain { 5 | chain: Array<_Block>; 6 | addBlock : (data: { transaction : [_Transaction] }) => void 7 | replaceChain: (chain : Array<_Block>) => _Errors | boolean 8 | validTransactionData : (chain: Array<_Block>) => boolean | _Errors 9 | } -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_Transaction.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_Transaction.ts: -------------------------------------------------------------------------------- 1 | import { _Errors } from "../../types/errors_interface"; 2 | import { inputMap_type } from "../../types/inputMap_types"; 3 | import { _Wallet } from "./_Wallet"; 4 | 5 | export interface _Transaction { 6 | id: string; 7 | inputMap: inputMap_type; 8 | outputMap: any; 9 | inputMapCreator: (senderWallet: _Wallet, outputMap: {}) => {}; 10 | outputMapCreator: ( 11 | senderWallet: _Wallet, 12 | amount: number, 13 | recipient: string 14 | ) => {}; 15 | update : (recipient: string,amount : number,senderWallet : _Wallet) => void | _Errors ; 16 | } 17 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_TransactionMiner.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_TransactionMiner.ts: -------------------------------------------------------------------------------- 1 | export interface _TransactionMiner{ 2 | mineTransaction() : Promise; 3 | } -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_TransactionPool.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_TransactionPool.ts: -------------------------------------------------------------------------------- 1 | import { _Transaction } from "./_Transaction"; 2 | import {_Wallet} from "./_Wallet"; 3 | import { _Block } from "./_Block"; 4 | export interface _TransactionPool { 5 | transactionMap : any, 6 | add : (transaction : _Transaction) => void ; 7 | isHave : (wallet : _Wallet) => _Transaction | undefined; 8 | clear : () => void; 9 | clearBlockchainTransactions : (chain : Array<_Block>) => void; 10 | } -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_Wallet.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/interfaces/Blockchain/_Wallet.ts: -------------------------------------------------------------------------------- 1 | import { _Transaction } from "./_Transaction"; 2 | import { _Errors } from "../../types/errors_interface"; 3 | import { _Block } from "./_Block"; 4 | export interface _Wallet { 5 | balance : number, 6 | keyPair : any, 7 | publicKey : string, 8 | privateKey : string, 9 | sign : (data : any) => string; 10 | createTransaction : ( recipient : string, amount : number, chain : Array<_Block>) => (_Errors | _Transaction) 11 | } -------------------------------------------------------------------------------- /Src/interfaces/Network/_Nodes.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/interfaces/Network/_Nodes.ts: -------------------------------------------------------------------------------- 1 | import { _Block } from "../Blockchain/_Block"; 2 | import { _Blockchain } from "../Blockchain/_Blockchain"; 3 | 4 | export interface _Nodes { 5 | list : Array, 6 | start : () => void, 7 | broadcast : (name : string , data : any) => Promise, 8 | bet : (name : string , callback : Function) => void 9 | } -------------------------------------------------------------------------------- /Src/interfaces/Network/_Root.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/interfaces/Network/_Root.ts: -------------------------------------------------------------------------------- 1 | import { _Errors } from "../../types/errors_interface"; 2 | import { _Block } from "../Blockchain/_Block"; 3 | 4 | export interface _Root { 5 | start: () => Promise<_Errors | boolean>; 6 | addMe: () => void | _Errors; 7 | giveData : (chain : Array<_Block>,nodeList : Array) => void | _Errors; 8 | bet: (name : string, callback : Function) => void; 9 | } 10 | -------------------------------------------------------------------------------- /Src/types/errors_interface.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/types/errors_interface.ts: -------------------------------------------------------------------------------- 1 | export interface _Errors { 2 | message: string; 3 | code: number; 4 | } 5 | -------------------------------------------------------------------------------- /Src/types/inputMap_types.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | -------------------------------------------------------------------------------- /Src/types/inputMap_types.ts: -------------------------------------------------------------------------------- 1 | import { SignatureInput } from "elliptic"; 2 | 3 | export type inputMap_type = { 4 | timestamp: number; 5 | address: string; 6 | amount: number; 7 | signature: SignatureInput; 8 | }; 9 | -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | exports.config = void 0; 4 | const DEFUALT_DIFFICULTY = 10; 5 | const REWARD_TRANSACTION = { 6 | address: '**DPX Blockchain**' 7 | }; 8 | const ROOT_URL = "127.0.0.1"; 9 | const REWARD = 10; 10 | exports.config = { 11 | NODE_PORT: 8765, 12 | ADMIN: { 13 | httpIP: `http://${ROOT_URL}:${8765}`, 14 | }, 15 | MINE_RATE: 1000 * 60 * 10, 16 | ROOT_URL, 17 | ROOT_PORT: 3001, 18 | GENESIS_DATA: { 19 | hash: "DEFAULT-DPX-GENESIS-HASH", 20 | lastHash: "DEFAULT-DPX-LAST-HASH", 21 | nonce: 0, 22 | difficulty: DEFUALT_DIFFICULTY, 23 | timestamp: 0, 24 | data: {}, 25 | }, 26 | DEFUALT_BALANCE: 0, 27 | REWARD_TRANSACTION, 28 | REWARD, 29 | }; 30 | -------------------------------------------------------------------------------- /config.ts: -------------------------------------------------------------------------------- 1 | const DEFUALT_DIFFICULTY = 10; 2 | import { _Block } from "./Src/interfaces/Blockchain/_Block"; 3 | import { _Transaction } from "./Src/interfaces/Blockchain/_Transaction"; 4 | const REWARD_TRANSACTION = { 5 | address : '**DPX Blockchain**' 6 | } 7 | const ROOT_URL = "127.0.0.1"; 8 | const REWARD = 10; 9 | export const config: { 10 | NODE_PORT : number, 11 | MINE_RATE: number; 12 | ADMIN : {}, 13 | GENESIS_DATA: _Block; 14 | DEFUALT_BALANCE: number; 15 | ROOT_URL: string; 16 | ROOT_PORT: number; 17 | REWARD_TRANSACTION : { 18 | address : string 19 | }; 20 | REWARD: number; 21 | } = { 22 | NODE_PORT : 8765, 23 | ADMIN : { 24 | httpIP : `http://${ROOT_URL}:${8765}`, 25 | }, 26 | MINE_RATE: 1000 * 60 * 10, 27 | ROOT_URL, 28 | ROOT_PORT: 3001, 29 | GENESIS_DATA: { 30 | hash: "DEFAULT-DPX-GENESIS-HASH", 31 | lastHash: "DEFAULT-DPX-LAST-HASH", 32 | nonce: 0, 33 | difficulty: DEFUALT_DIFFICULTY, 34 | timestamp: 0, 35 | data: {}, 36 | }, 37 | DEFUALT_BALANCE: 0, 38 | REWARD_TRANSACTION, 39 | REWARD, 40 | }; 41 | -------------------------------------------------------------------------------- /errors.txt: -------------------------------------------------------------------------------- 1 | - errors list 2 | 3 | -- 100 - validation 4 | 5 | --- 101 - chain is short 6 | --- 102 - chain is not valid 7 | --- 111 - invalid transaction 8 | 9 | -- 200 - connection 10 | 11 | --- 250 - error connecting to the root server 12 | --- 251 - connect to the root server of timeout -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | try { 2 | const express = require("express"); 3 | const app = express(); 4 | 5 | const { Blockchain } = require("./Src/classes/Blockchain/Blockchain"); 6 | const { 7 | TransactionPool, 8 | } = require("./Src/classes/Blockchain/TransactionPool"); 9 | const { Transaction } = require("./Src/classes/Blockchain/Transaction"); 10 | const transactionPool = new TransactionPool(); 11 | const { 12 | config: { ADMIN }, config, 13 | } = require("./config"); 14 | 15 | let nodeList = [ADMIN.httpIP]; 16 | 17 | const axios = require("axios").default; 18 | 19 | const net = require("net"); 20 | 21 | const server = net.createServer(); 22 | 23 | const blockChain = new Blockchain(); 24 | console.log = ()=>{}; 25 | class SocketCtrl { 26 | constructor() { 27 | this.sockets = []; 28 | this.mainSocket; 29 | } 30 | slice(number) { 31 | this.sockets.forEach((x) => { 32 | x.write(JSON.stringify({ action: "sliceChain", data: number })); 33 | }); 34 | } 35 | reaplceChain(chain) { 36 | this.sockets.forEach((x) => { 37 | x.write(JSON.stringify({ action: "replaceChain", data: chain })); 38 | }); 39 | } 40 | reaplceNode(nodeList) { 41 | this.sockets.forEach((x) => { 42 | x.write(JSON.stringify({ action: "replaceNodes", data: nodeList })); 43 | }); 44 | } 45 | addNode(ip) { 46 | this.sockets.forEach((x) => { 47 | x.write(JSON.stringify({ action: "newNode", data: ip })); 48 | }); 49 | } 50 | help(ip) { 51 | this.mainSocket = ip; 52 | } 53 | } 54 | 55 | const socketCtrl = new SocketCtrl(); 56 | server.on("connection", (socket) => { 57 | console.log(`${socket.remoteAddress}:${socket.remotePort}`); 58 | 59 | if ( 60 | socketCtrl.mainSocket == `${socket.remoteAddress}:${socket.remotePort}` 61 | ) { 62 | socket.write(JSON.stringify({ action: "giveMeData" })); 63 | } 64 | 65 | socket.on("data", (data) => { 66 | data = JSON.parse(data.toString()); 67 | if (data.action == "addMe") { 68 | socket.id = `${socket.remoteAddress}:${socket.remotePort}`; 69 | socket.write( 70 | JSON.stringify({ 71 | action: "welcome", 72 | data: { 73 | nodeList, 74 | chain: blockChain.chain, 75 | transactionMap: transactionPool.transactionMap, 76 | }, 77 | }) 78 | ); 79 | nodeList.push(`${socket.remoteAddress}:${socket.remotePort - 2}`); 80 | socketCtrl.addNode(`${socket.remoteAddress}:${socket.remotePort - 2}`); 81 | socketCtrl.sockets.push(socket); 82 | } 83 | if (data.action === "dataForYou" && socket.id == socketCtrl.mainSocket) { 84 | nodeList = data.data.nodeList; 85 | blockChain.chain = data.data.chain; 86 | socketCtrl.reaplceChain(data.data.chain); 87 | socketCtrl.reaplceNode(data.data.nodeList); 88 | } 89 | }); 90 | 91 | socket.on("error", (err) => { 92 | console.log("app is have problem :", err); 93 | }); 94 | socket.on("end", () => { 95 | socketCtrl.sockets = socketCtrl.sockets.filter((x) => x.id != socket.id); 96 | }); 97 | }); 98 | 99 | server.on("close", () => { 100 | console.log("netword has been closed"); 101 | }); 102 | server.on("error", (err) => { 103 | console.log(`error : ${err}`); 104 | }); 105 | server.on("listening", () => { 106 | console.log("admin network is runnig"); 107 | }); 108 | server.listen({ 109 | port: 3001, 110 | host : '0.0.0.0' 111 | }); 112 | 113 | app.use(express.json()); 114 | app.use((req, res, next) => { 115 | next(); 116 | }); 117 | app.use((req, res, next) => { 118 | if ( 119 | nodeList.find((x) => req.ip.replace("::ffff:", "") === x.split(":")[0]) 120 | ) { 121 | next(); 122 | } else { 123 | res.send("who are you ?"); 124 | } 125 | }); 126 | 127 | app.post("/chain", (req, res, next) => { 128 | try { 129 | const data = req.body; 130 | if ( 131 | blockChain.validTransactionData(data) === true && 132 | blockChain.replaceChain(data) === true 133 | ) { 134 | transactionPool.clearBlockchainTransactions(data); 135 | res.send("ok"); 136 | } 137 | } catch (err) { 138 | next(err); 139 | } 140 | }); 141 | 142 | app.post("/transaction", (req, res, next) => { 143 | try { 144 | const check = Transaction.isValid(req.body); 145 | if (check !== true) { 146 | return check; 147 | } 148 | transactionPool.add(req.body); 149 | res.send("ok"); 150 | } catch (err) { 151 | next(err); 152 | } 153 | }); 154 | 155 | app.post("/blocks", (req, res, next) => { 156 | try { 157 | res.status(200).json(blockChain.chain); 158 | } catch (err) { 159 | next(err); 160 | } 161 | }); 162 | 163 | setInterval(() => { 164 | for (let i = 0; i < nodeList.length; i++) { 165 | axios 166 | .get(`http://${nodeList[i]}/blocks`) 167 | .then(() => {}) 168 | .catch(() => { 169 | nodeList = nodeList.filter((x) => x != nodeList[i]); 170 | socketCtrl.reaplceNode(nodeList); 171 | }); 172 | } 173 | if (fs.existsSync("./chain.log")) { 174 | fs.unlinkSync("./chain.log"); 175 | fs.writeFileSync("./chain.log", JSON.stringify(blockChain.chain)); 176 | } else { 177 | fs.writeFileSync("./chain.log", JSON.stringify(blockChain.chain)); 178 | } 179 | if (fs.existsSync("./nodes.log")) { 180 | fs.unlinkSync("./nodes.log"); 181 | fs.writeFileSync("./nodes.log", JSON.stringify(nodeList)); 182 | } else { 183 | fs.writeFileSync("./nodes.log", JSON.stringify(nodeList)); 184 | } 185 | }, 1000 * 60 * 60); 186 | 187 | // listen app 188 | 189 | app.listen(process.env.PORT || config.NODE_PORT || 45451, () => { 190 | console.log("admin is runnig"); 191 | }); 192 | } catch (error) { 193 | console.error(error); 194 | } 195 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Admin-Blockchain", 3 | "lockfileVersion": 2, 4 | "requires": true, 5 | "packages": { 6 | "": { 7 | "dependencies": { 8 | "@types/node": "^17.0.23", 9 | "axios": "^0.26.1", 10 | "cls.js": "^1.5.0", 11 | "elliptic": "^6.5.4", 12 | "express": "^4.17.3", 13 | "hex-to-bin": "^1.0.1", 14 | "hex-to-binary": "^1.0.1", 15 | "uniqid": "^5.4.0" 16 | }, 17 | "devDependencies": { 18 | "@types/elliptic": "^6.4.14", 19 | "@types/express": "^4.17.13", 20 | "@types/uniqid": "^5.3.2", 21 | "@types/uuid": "^8.3.4" 22 | } 23 | }, 24 | "node_modules/@types/bn.js": { 25 | "version": "5.1.0", 26 | "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", 27 | "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", 28 | "dev": true, 29 | "dependencies": { 30 | "@types/node": "*" 31 | } 32 | }, 33 | "node_modules/@types/body-parser": { 34 | "version": "1.19.2", 35 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", 36 | "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", 37 | "dev": true, 38 | "dependencies": { 39 | "@types/connect": "*", 40 | "@types/node": "*" 41 | } 42 | }, 43 | "node_modules/@types/connect": { 44 | "version": "3.4.35", 45 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", 46 | "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", 47 | "dev": true, 48 | "dependencies": { 49 | "@types/node": "*" 50 | } 51 | }, 52 | "node_modules/@types/elliptic": { 53 | "version": "6.4.14", 54 | "resolved": "https://registry.npmjs.org/@types/elliptic/-/elliptic-6.4.14.tgz", 55 | "integrity": "sha512-z4OBcDAU0GVwDTuwJzQCiL6188QvZMkvoERgcVjq0/mPM8jCfdwZ3x5zQEVoL9WCAru3aG5wl3Z5Ww5wBWn7ZQ==", 56 | "dev": true, 57 | "dependencies": { 58 | "@types/bn.js": "*" 59 | } 60 | }, 61 | "node_modules/@types/express": { 62 | "version": "4.17.13", 63 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", 64 | "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", 65 | "dev": true, 66 | "dependencies": { 67 | "@types/body-parser": "*", 68 | "@types/express-serve-static-core": "^4.17.18", 69 | "@types/qs": "*", 70 | "@types/serve-static": "*" 71 | } 72 | }, 73 | "node_modules/@types/express-serve-static-core": { 74 | "version": "4.17.28", 75 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", 76 | "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", 77 | "dev": true, 78 | "dependencies": { 79 | "@types/node": "*", 80 | "@types/qs": "*", 81 | "@types/range-parser": "*" 82 | } 83 | }, 84 | "node_modules/@types/mime": { 85 | "version": "1.3.2", 86 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", 87 | "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", 88 | "dev": true 89 | }, 90 | "node_modules/@types/node": { 91 | "version": "17.0.23", 92 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", 93 | "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" 94 | }, 95 | "node_modules/@types/qs": { 96 | "version": "6.9.7", 97 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", 98 | "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", 99 | "dev": true 100 | }, 101 | "node_modules/@types/range-parser": { 102 | "version": "1.2.4", 103 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", 104 | "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", 105 | "dev": true 106 | }, 107 | "node_modules/@types/serve-static": { 108 | "version": "1.13.10", 109 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", 110 | "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", 111 | "dev": true, 112 | "dependencies": { 113 | "@types/mime": "^1", 114 | "@types/node": "*" 115 | } 116 | }, 117 | "node_modules/@types/uniqid": { 118 | "version": "5.3.2", 119 | "resolved": "https://registry.npmjs.org/@types/uniqid/-/uniqid-5.3.2.tgz", 120 | "integrity": "sha512-/NYoaZpWsnAJDsGYeMNDeG3p3fuUb4AiC7MfKxi5VSu18tXd08w6Ch0fKW94T4FeLXXZwZPoFgHA1O0rDYKyMQ==", 121 | "dev": true 122 | }, 123 | "node_modules/@types/uuid": { 124 | "version": "8.3.4", 125 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", 126 | "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", 127 | "dev": true 128 | }, 129 | "node_modules/accepts": { 130 | "version": "1.3.8", 131 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 132 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 133 | "dependencies": { 134 | "mime-types": "~2.1.34", 135 | "negotiator": "0.6.3" 136 | }, 137 | "engines": { 138 | "node": ">= 0.6" 139 | } 140 | }, 141 | "node_modules/array-flatten": { 142 | "version": "1.1.1", 143 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 144 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 145 | }, 146 | "node_modules/axios": { 147 | "version": "0.26.1", 148 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", 149 | "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", 150 | "dependencies": { 151 | "follow-redirects": "^1.14.8" 152 | } 153 | }, 154 | "node_modules/bn.js": { 155 | "version": "4.12.0", 156 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 157 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" 158 | }, 159 | "node_modules/body-parser": { 160 | "version": "1.19.2", 161 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", 162 | "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", 163 | "dependencies": { 164 | "bytes": "3.1.2", 165 | "content-type": "~1.0.4", 166 | "debug": "2.6.9", 167 | "depd": "~1.1.2", 168 | "http-errors": "1.8.1", 169 | "iconv-lite": "0.4.24", 170 | "on-finished": "~2.3.0", 171 | "qs": "6.9.7", 172 | "raw-body": "2.4.3", 173 | "type-is": "~1.6.18" 174 | }, 175 | "engines": { 176 | "node": ">= 0.8" 177 | } 178 | }, 179 | "node_modules/brorand": { 180 | "version": "1.1.0", 181 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", 182 | "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" 183 | }, 184 | "node_modules/bytes": { 185 | "version": "3.1.2", 186 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 187 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", 188 | "engines": { 189 | "node": ">= 0.8" 190 | } 191 | }, 192 | "node_modules/cls.js": { 193 | "version": "1.5.0", 194 | "resolved": "https://registry.npmjs.org/cls.js/-/cls.js-1.5.0.tgz", 195 | "integrity": "sha512-p7IWSmtauF5DfmY/C2nuCn/4nD61fk4I9eLyxegEqE3W/CwojU8wovKqoi9qIhsCdgmjav+SWidG0o+pZTDxXw==" 196 | }, 197 | "node_modules/content-disposition": { 198 | "version": "0.5.4", 199 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 200 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 201 | "dependencies": { 202 | "safe-buffer": "5.2.1" 203 | }, 204 | "engines": { 205 | "node": ">= 0.6" 206 | } 207 | }, 208 | "node_modules/content-type": { 209 | "version": "1.0.4", 210 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 211 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", 212 | "engines": { 213 | "node": ">= 0.6" 214 | } 215 | }, 216 | "node_modules/cookie": { 217 | "version": "0.4.2", 218 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", 219 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", 220 | "engines": { 221 | "node": ">= 0.6" 222 | } 223 | }, 224 | "node_modules/cookie-signature": { 225 | "version": "1.0.6", 226 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 227 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 228 | }, 229 | "node_modules/debug": { 230 | "version": "2.6.9", 231 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 232 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 233 | "dependencies": { 234 | "ms": "2.0.0" 235 | } 236 | }, 237 | "node_modules/depd": { 238 | "version": "1.1.2", 239 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 240 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", 241 | "engines": { 242 | "node": ">= 0.6" 243 | } 244 | }, 245 | "node_modules/destroy": { 246 | "version": "1.0.4", 247 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 248 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 249 | }, 250 | "node_modules/ee-first": { 251 | "version": "1.1.1", 252 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 253 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 254 | }, 255 | "node_modules/elliptic": { 256 | "version": "6.5.4", 257 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", 258 | "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", 259 | "dependencies": { 260 | "bn.js": "^4.11.9", 261 | "brorand": "^1.1.0", 262 | "hash.js": "^1.0.0", 263 | "hmac-drbg": "^1.0.1", 264 | "inherits": "^2.0.4", 265 | "minimalistic-assert": "^1.0.1", 266 | "minimalistic-crypto-utils": "^1.0.1" 267 | } 268 | }, 269 | "node_modules/encodeurl": { 270 | "version": "1.0.2", 271 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 272 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", 273 | "engines": { 274 | "node": ">= 0.8" 275 | } 276 | }, 277 | "node_modules/escape-html": { 278 | "version": "1.0.3", 279 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 280 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 281 | }, 282 | "node_modules/etag": { 283 | "version": "1.8.1", 284 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 285 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", 286 | "engines": { 287 | "node": ">= 0.6" 288 | } 289 | }, 290 | "node_modules/express": { 291 | "version": "4.17.3", 292 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", 293 | "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", 294 | "dependencies": { 295 | "accepts": "~1.3.8", 296 | "array-flatten": "1.1.1", 297 | "body-parser": "1.19.2", 298 | "content-disposition": "0.5.4", 299 | "content-type": "~1.0.4", 300 | "cookie": "0.4.2", 301 | "cookie-signature": "1.0.6", 302 | "debug": "2.6.9", 303 | "depd": "~1.1.2", 304 | "encodeurl": "~1.0.2", 305 | "escape-html": "~1.0.3", 306 | "etag": "~1.8.1", 307 | "finalhandler": "~1.1.2", 308 | "fresh": "0.5.2", 309 | "merge-descriptors": "1.0.1", 310 | "methods": "~1.1.2", 311 | "on-finished": "~2.3.0", 312 | "parseurl": "~1.3.3", 313 | "path-to-regexp": "0.1.7", 314 | "proxy-addr": "~2.0.7", 315 | "qs": "6.9.7", 316 | "range-parser": "~1.2.1", 317 | "safe-buffer": "5.2.1", 318 | "send": "0.17.2", 319 | "serve-static": "1.14.2", 320 | "setprototypeof": "1.2.0", 321 | "statuses": "~1.5.0", 322 | "type-is": "~1.6.18", 323 | "utils-merge": "1.0.1", 324 | "vary": "~1.1.2" 325 | }, 326 | "engines": { 327 | "node": ">= 0.10.0" 328 | } 329 | }, 330 | "node_modules/finalhandler": { 331 | "version": "1.1.2", 332 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 333 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 334 | "dependencies": { 335 | "debug": "2.6.9", 336 | "encodeurl": "~1.0.2", 337 | "escape-html": "~1.0.3", 338 | "on-finished": "~2.3.0", 339 | "parseurl": "~1.3.3", 340 | "statuses": "~1.5.0", 341 | "unpipe": "~1.0.0" 342 | }, 343 | "engines": { 344 | "node": ">= 0.8" 345 | } 346 | }, 347 | "node_modules/follow-redirects": { 348 | "version": "1.14.9", 349 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", 350 | "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==", 351 | "funding": [ 352 | { 353 | "type": "individual", 354 | "url": "https://github.com/sponsors/RubenVerborgh" 355 | } 356 | ], 357 | "engines": { 358 | "node": ">=4.0" 359 | }, 360 | "peerDependenciesMeta": { 361 | "debug": { 362 | "optional": true 363 | } 364 | } 365 | }, 366 | "node_modules/forwarded": { 367 | "version": "0.2.0", 368 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 369 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", 370 | "engines": { 371 | "node": ">= 0.6" 372 | } 373 | }, 374 | "node_modules/fresh": { 375 | "version": "0.5.2", 376 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 377 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", 378 | "engines": { 379 | "node": ">= 0.6" 380 | } 381 | }, 382 | "node_modules/hash.js": { 383 | "version": "1.1.7", 384 | "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", 385 | "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", 386 | "dependencies": { 387 | "inherits": "^2.0.3", 388 | "minimalistic-assert": "^1.0.1" 389 | } 390 | }, 391 | "node_modules/hex-to-bin": { 392 | "version": "1.0.1", 393 | "resolved": "https://registry.npmjs.org/hex-to-bin/-/hex-to-bin-1.0.1.tgz", 394 | "integrity": "sha512-qKdiDve+8NxdC3w/bINXfKMiv2oPK0T7RHowDEwrzEbdebKjEZqiMz1aMMXbuULjq6Qo9Yg8jLVnlpYRUKMFPQ==" 395 | }, 396 | "node_modules/hex-to-binary": { 397 | "version": "1.0.1", 398 | "resolved": "https://registry.npmjs.org/hex-to-binary/-/hex-to-binary-1.0.1.tgz", 399 | "integrity": "sha1-YcevAW/CK86pcE2fLpo46MfbuFQ=" 400 | }, 401 | "node_modules/hmac-drbg": { 402 | "version": "1.0.1", 403 | "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", 404 | "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", 405 | "dependencies": { 406 | "hash.js": "^1.0.3", 407 | "minimalistic-assert": "^1.0.0", 408 | "minimalistic-crypto-utils": "^1.0.1" 409 | } 410 | }, 411 | "node_modules/http-errors": { 412 | "version": "1.8.1", 413 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", 414 | "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", 415 | "dependencies": { 416 | "depd": "~1.1.2", 417 | "inherits": "2.0.4", 418 | "setprototypeof": "1.2.0", 419 | "statuses": ">= 1.5.0 < 2", 420 | "toidentifier": "1.0.1" 421 | }, 422 | "engines": { 423 | "node": ">= 0.6" 424 | } 425 | }, 426 | "node_modules/iconv-lite": { 427 | "version": "0.4.24", 428 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 429 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 430 | "dependencies": { 431 | "safer-buffer": ">= 2.1.2 < 3" 432 | }, 433 | "engines": { 434 | "node": ">=0.10.0" 435 | } 436 | }, 437 | "node_modules/inherits": { 438 | "version": "2.0.4", 439 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 440 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 441 | }, 442 | "node_modules/ipaddr.js": { 443 | "version": "1.9.1", 444 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 445 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", 446 | "engines": { 447 | "node": ">= 0.10" 448 | } 449 | }, 450 | "node_modules/media-typer": { 451 | "version": "0.3.0", 452 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 453 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", 454 | "engines": { 455 | "node": ">= 0.6" 456 | } 457 | }, 458 | "node_modules/merge-descriptors": { 459 | "version": "1.0.1", 460 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 461 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 462 | }, 463 | "node_modules/methods": { 464 | "version": "1.1.2", 465 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 466 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", 467 | "engines": { 468 | "node": ">= 0.6" 469 | } 470 | }, 471 | "node_modules/mime": { 472 | "version": "1.6.0", 473 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 474 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", 475 | "bin": { 476 | "mime": "cli.js" 477 | }, 478 | "engines": { 479 | "node": ">=4" 480 | } 481 | }, 482 | "node_modules/mime-db": { 483 | "version": "1.52.0", 484 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 485 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", 486 | "engines": { 487 | "node": ">= 0.6" 488 | } 489 | }, 490 | "node_modules/mime-types": { 491 | "version": "2.1.35", 492 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 493 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 494 | "dependencies": { 495 | "mime-db": "1.52.0" 496 | }, 497 | "engines": { 498 | "node": ">= 0.6" 499 | } 500 | }, 501 | "node_modules/minimalistic-assert": { 502 | "version": "1.0.1", 503 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 504 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" 505 | }, 506 | "node_modules/minimalistic-crypto-utils": { 507 | "version": "1.0.1", 508 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 509 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" 510 | }, 511 | "node_modules/ms": { 512 | "version": "2.0.0", 513 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 514 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 515 | }, 516 | "node_modules/negotiator": { 517 | "version": "0.6.3", 518 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 519 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", 520 | "engines": { 521 | "node": ">= 0.6" 522 | } 523 | }, 524 | "node_modules/on-finished": { 525 | "version": "2.3.0", 526 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 527 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 528 | "dependencies": { 529 | "ee-first": "1.1.1" 530 | }, 531 | "engines": { 532 | "node": ">= 0.8" 533 | } 534 | }, 535 | "node_modules/parseurl": { 536 | "version": "1.3.3", 537 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 538 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", 539 | "engines": { 540 | "node": ">= 0.8" 541 | } 542 | }, 543 | "node_modules/path-to-regexp": { 544 | "version": "0.1.7", 545 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 546 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 547 | }, 548 | "node_modules/proxy-addr": { 549 | "version": "2.0.7", 550 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 551 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 552 | "dependencies": { 553 | "forwarded": "0.2.0", 554 | "ipaddr.js": "1.9.1" 555 | }, 556 | "engines": { 557 | "node": ">= 0.10" 558 | } 559 | }, 560 | "node_modules/qs": { 561 | "version": "6.9.7", 562 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", 563 | "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==", 564 | "engines": { 565 | "node": ">=0.6" 566 | }, 567 | "funding": { 568 | "url": "https://github.com/sponsors/ljharb" 569 | } 570 | }, 571 | "node_modules/range-parser": { 572 | "version": "1.2.1", 573 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 574 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", 575 | "engines": { 576 | "node": ">= 0.6" 577 | } 578 | }, 579 | "node_modules/raw-body": { 580 | "version": "2.4.3", 581 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", 582 | "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", 583 | "dependencies": { 584 | "bytes": "3.1.2", 585 | "http-errors": "1.8.1", 586 | "iconv-lite": "0.4.24", 587 | "unpipe": "1.0.0" 588 | }, 589 | "engines": { 590 | "node": ">= 0.8" 591 | } 592 | }, 593 | "node_modules/safe-buffer": { 594 | "version": "5.2.1", 595 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 596 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 597 | "funding": [ 598 | { 599 | "type": "github", 600 | "url": "https://github.com/sponsors/feross" 601 | }, 602 | { 603 | "type": "patreon", 604 | "url": "https://www.patreon.com/feross" 605 | }, 606 | { 607 | "type": "consulting", 608 | "url": "https://feross.org/support" 609 | } 610 | ] 611 | }, 612 | "node_modules/safer-buffer": { 613 | "version": "2.1.2", 614 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 615 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 616 | }, 617 | "node_modules/send": { 618 | "version": "0.17.2", 619 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", 620 | "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", 621 | "dependencies": { 622 | "debug": "2.6.9", 623 | "depd": "~1.1.2", 624 | "destroy": "~1.0.4", 625 | "encodeurl": "~1.0.2", 626 | "escape-html": "~1.0.3", 627 | "etag": "~1.8.1", 628 | "fresh": "0.5.2", 629 | "http-errors": "1.8.1", 630 | "mime": "1.6.0", 631 | "ms": "2.1.3", 632 | "on-finished": "~2.3.0", 633 | "range-parser": "~1.2.1", 634 | "statuses": "~1.5.0" 635 | }, 636 | "engines": { 637 | "node": ">= 0.8.0" 638 | } 639 | }, 640 | "node_modules/send/node_modules/ms": { 641 | "version": "2.1.3", 642 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 643 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 644 | }, 645 | "node_modules/serve-static": { 646 | "version": "1.14.2", 647 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", 648 | "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", 649 | "dependencies": { 650 | "encodeurl": "~1.0.2", 651 | "escape-html": "~1.0.3", 652 | "parseurl": "~1.3.3", 653 | "send": "0.17.2" 654 | }, 655 | "engines": { 656 | "node": ">= 0.8.0" 657 | } 658 | }, 659 | "node_modules/setprototypeof": { 660 | "version": "1.2.0", 661 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 662 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 663 | }, 664 | "node_modules/statuses": { 665 | "version": "1.5.0", 666 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 667 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", 668 | "engines": { 669 | "node": ">= 0.6" 670 | } 671 | }, 672 | "node_modules/toidentifier": { 673 | "version": "1.0.1", 674 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 675 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", 676 | "engines": { 677 | "node": ">=0.6" 678 | } 679 | }, 680 | "node_modules/type-is": { 681 | "version": "1.6.18", 682 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 683 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 684 | "dependencies": { 685 | "media-typer": "0.3.0", 686 | "mime-types": "~2.1.24" 687 | }, 688 | "engines": { 689 | "node": ">= 0.6" 690 | } 691 | }, 692 | "node_modules/uniqid": { 693 | "version": "5.4.0", 694 | "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz", 695 | "integrity": "sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==" 696 | }, 697 | "node_modules/unpipe": { 698 | "version": "1.0.0", 699 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 700 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", 701 | "engines": { 702 | "node": ">= 0.8" 703 | } 704 | }, 705 | "node_modules/utils-merge": { 706 | "version": "1.0.1", 707 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 708 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", 709 | "engines": { 710 | "node": ">= 0.4.0" 711 | } 712 | }, 713 | "node_modules/vary": { 714 | "version": "1.1.2", 715 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 716 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", 717 | "engines": { 718 | "node": ">= 0.8" 719 | } 720 | } 721 | }, 722 | "dependencies": { 723 | "@types/bn.js": { 724 | "version": "5.1.0", 725 | "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz", 726 | "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==", 727 | "dev": true, 728 | "requires": { 729 | "@types/node": "*" 730 | } 731 | }, 732 | "@types/body-parser": { 733 | "version": "1.19.2", 734 | "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", 735 | "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", 736 | "dev": true, 737 | "requires": { 738 | "@types/connect": "*", 739 | "@types/node": "*" 740 | } 741 | }, 742 | "@types/connect": { 743 | "version": "3.4.35", 744 | "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", 745 | "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", 746 | "dev": true, 747 | "requires": { 748 | "@types/node": "*" 749 | } 750 | }, 751 | "@types/elliptic": { 752 | "version": "6.4.14", 753 | "resolved": "https://registry.npmjs.org/@types/elliptic/-/elliptic-6.4.14.tgz", 754 | "integrity": "sha512-z4OBcDAU0GVwDTuwJzQCiL6188QvZMkvoERgcVjq0/mPM8jCfdwZ3x5zQEVoL9WCAru3aG5wl3Z5Ww5wBWn7ZQ==", 755 | "dev": true, 756 | "requires": { 757 | "@types/bn.js": "*" 758 | } 759 | }, 760 | "@types/express": { 761 | "version": "4.17.13", 762 | "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz", 763 | "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==", 764 | "dev": true, 765 | "requires": { 766 | "@types/body-parser": "*", 767 | "@types/express-serve-static-core": "^4.17.18", 768 | "@types/qs": "*", 769 | "@types/serve-static": "*" 770 | } 771 | }, 772 | "@types/express-serve-static-core": { 773 | "version": "4.17.28", 774 | "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.28.tgz", 775 | "integrity": "sha512-P1BJAEAW3E2DJUlkgq4tOL3RyMunoWXqbSCygWo5ZIWTjUgN1YnaXWW4VWl/oc8vs/XoYibEGBKP0uZyF4AHig==", 776 | "dev": true, 777 | "requires": { 778 | "@types/node": "*", 779 | "@types/qs": "*", 780 | "@types/range-parser": "*" 781 | } 782 | }, 783 | "@types/mime": { 784 | "version": "1.3.2", 785 | "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", 786 | "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", 787 | "dev": true 788 | }, 789 | "@types/node": { 790 | "version": "17.0.23", 791 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.23.tgz", 792 | "integrity": "sha512-UxDxWn7dl97rKVeVS61vErvw086aCYhDLyvRQZ5Rk65rZKepaFdm53GeqXaKBuOhED4e9uWq34IC3TdSdJJ2Gw==" 793 | }, 794 | "@types/qs": { 795 | "version": "6.9.7", 796 | "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", 797 | "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", 798 | "dev": true 799 | }, 800 | "@types/range-parser": { 801 | "version": "1.2.4", 802 | "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", 803 | "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", 804 | "dev": true 805 | }, 806 | "@types/serve-static": { 807 | "version": "1.13.10", 808 | "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz", 809 | "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==", 810 | "dev": true, 811 | "requires": { 812 | "@types/mime": "^1", 813 | "@types/node": "*" 814 | } 815 | }, 816 | "@types/uniqid": { 817 | "version": "5.3.2", 818 | "resolved": "https://registry.npmjs.org/@types/uniqid/-/uniqid-5.3.2.tgz", 819 | "integrity": "sha512-/NYoaZpWsnAJDsGYeMNDeG3p3fuUb4AiC7MfKxi5VSu18tXd08w6Ch0fKW94T4FeLXXZwZPoFgHA1O0rDYKyMQ==", 820 | "dev": true 821 | }, 822 | "@types/uuid": { 823 | "version": "8.3.4", 824 | "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz", 825 | "integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==", 826 | "dev": true 827 | }, 828 | "accepts": { 829 | "version": "1.3.8", 830 | "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", 831 | "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", 832 | "requires": { 833 | "mime-types": "~2.1.34", 834 | "negotiator": "0.6.3" 835 | } 836 | }, 837 | "array-flatten": { 838 | "version": "1.1.1", 839 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", 840 | "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" 841 | }, 842 | "axios": { 843 | "version": "0.26.1", 844 | "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", 845 | "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", 846 | "requires": { 847 | "follow-redirects": "^1.14.8" 848 | } 849 | }, 850 | "bn.js": { 851 | "version": "4.12.0", 852 | "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", 853 | "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" 854 | }, 855 | "body-parser": { 856 | "version": "1.19.2", 857 | "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.2.tgz", 858 | "integrity": "sha512-SAAwOxgoCKMGs9uUAUFHygfLAyaniaoun6I8mFY9pRAJL9+Kec34aU+oIjDhTycub1jozEfEwx1W1IuOYxVSFw==", 859 | "requires": { 860 | "bytes": "3.1.2", 861 | "content-type": "~1.0.4", 862 | "debug": "2.6.9", 863 | "depd": "~1.1.2", 864 | "http-errors": "1.8.1", 865 | "iconv-lite": "0.4.24", 866 | "on-finished": "~2.3.0", 867 | "qs": "6.9.7", 868 | "raw-body": "2.4.3", 869 | "type-is": "~1.6.18" 870 | } 871 | }, 872 | "brorand": { 873 | "version": "1.1.0", 874 | "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", 875 | "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=" 876 | }, 877 | "bytes": { 878 | "version": "3.1.2", 879 | "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", 880 | "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" 881 | }, 882 | "cls.js": { 883 | "version": "1.5.0", 884 | "resolved": "https://registry.npmjs.org/cls.js/-/cls.js-1.5.0.tgz", 885 | "integrity": "sha512-p7IWSmtauF5DfmY/C2nuCn/4nD61fk4I9eLyxegEqE3W/CwojU8wovKqoi9qIhsCdgmjav+SWidG0o+pZTDxXw==" 886 | }, 887 | "content-disposition": { 888 | "version": "0.5.4", 889 | "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", 890 | "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", 891 | "requires": { 892 | "safe-buffer": "5.2.1" 893 | } 894 | }, 895 | "content-type": { 896 | "version": "1.0.4", 897 | "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", 898 | "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" 899 | }, 900 | "cookie": { 901 | "version": "0.4.2", 902 | "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", 903 | "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" 904 | }, 905 | "cookie-signature": { 906 | "version": "1.0.6", 907 | "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", 908 | "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" 909 | }, 910 | "debug": { 911 | "version": "2.6.9", 912 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 913 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 914 | "requires": { 915 | "ms": "2.0.0" 916 | } 917 | }, 918 | "depd": { 919 | "version": "1.1.2", 920 | "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", 921 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" 922 | }, 923 | "destroy": { 924 | "version": "1.0.4", 925 | "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", 926 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" 927 | }, 928 | "ee-first": { 929 | "version": "1.1.1", 930 | "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", 931 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" 932 | }, 933 | "elliptic": { 934 | "version": "6.5.4", 935 | "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", 936 | "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", 937 | "requires": { 938 | "bn.js": "^4.11.9", 939 | "brorand": "^1.1.0", 940 | "hash.js": "^1.0.0", 941 | "hmac-drbg": "^1.0.1", 942 | "inherits": "^2.0.4", 943 | "minimalistic-assert": "^1.0.1", 944 | "minimalistic-crypto-utils": "^1.0.1" 945 | } 946 | }, 947 | "encodeurl": { 948 | "version": "1.0.2", 949 | "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", 950 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" 951 | }, 952 | "escape-html": { 953 | "version": "1.0.3", 954 | "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", 955 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" 956 | }, 957 | "etag": { 958 | "version": "1.8.1", 959 | "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", 960 | "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" 961 | }, 962 | "express": { 963 | "version": "4.17.3", 964 | "resolved": "https://registry.npmjs.org/express/-/express-4.17.3.tgz", 965 | "integrity": "sha512-yuSQpz5I+Ch7gFrPCk4/c+dIBKlQUxtgwqzph132bsT6qhuzss6I8cLJQz7B3rFblzd6wtcI0ZbGltH/C4LjUg==", 966 | "requires": { 967 | "accepts": "~1.3.8", 968 | "array-flatten": "1.1.1", 969 | "body-parser": "1.19.2", 970 | "content-disposition": "0.5.4", 971 | "content-type": "~1.0.4", 972 | "cookie": "0.4.2", 973 | "cookie-signature": "1.0.6", 974 | "debug": "2.6.9", 975 | "depd": "~1.1.2", 976 | "encodeurl": "~1.0.2", 977 | "escape-html": "~1.0.3", 978 | "etag": "~1.8.1", 979 | "finalhandler": "~1.1.2", 980 | "fresh": "0.5.2", 981 | "merge-descriptors": "1.0.1", 982 | "methods": "~1.1.2", 983 | "on-finished": "~2.3.0", 984 | "parseurl": "~1.3.3", 985 | "path-to-regexp": "0.1.7", 986 | "proxy-addr": "~2.0.7", 987 | "qs": "6.9.7", 988 | "range-parser": "~1.2.1", 989 | "safe-buffer": "5.2.1", 990 | "send": "0.17.2", 991 | "serve-static": "1.14.2", 992 | "setprototypeof": "1.2.0", 993 | "statuses": "~1.5.0", 994 | "type-is": "~1.6.18", 995 | "utils-merge": "1.0.1", 996 | "vary": "~1.1.2" 997 | } 998 | }, 999 | "finalhandler": { 1000 | "version": "1.1.2", 1001 | "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", 1002 | "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", 1003 | "requires": { 1004 | "debug": "2.6.9", 1005 | "encodeurl": "~1.0.2", 1006 | "escape-html": "~1.0.3", 1007 | "on-finished": "~2.3.0", 1008 | "parseurl": "~1.3.3", 1009 | "statuses": "~1.5.0", 1010 | "unpipe": "~1.0.0" 1011 | } 1012 | }, 1013 | "follow-redirects": { 1014 | "version": "1.14.9", 1015 | "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", 1016 | "integrity": "sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==" 1017 | }, 1018 | "forwarded": { 1019 | "version": "0.2.0", 1020 | "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", 1021 | "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==" 1022 | }, 1023 | "fresh": { 1024 | "version": "0.5.2", 1025 | "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", 1026 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" 1027 | }, 1028 | "hash.js": { 1029 | "version": "1.1.7", 1030 | "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", 1031 | "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", 1032 | "requires": { 1033 | "inherits": "^2.0.3", 1034 | "minimalistic-assert": "^1.0.1" 1035 | } 1036 | }, 1037 | "hex-to-bin": { 1038 | "version": "1.0.1", 1039 | "resolved": "https://registry.npmjs.org/hex-to-bin/-/hex-to-bin-1.0.1.tgz", 1040 | "integrity": "sha512-qKdiDve+8NxdC3w/bINXfKMiv2oPK0T7RHowDEwrzEbdebKjEZqiMz1aMMXbuULjq6Qo9Yg8jLVnlpYRUKMFPQ==" 1041 | }, 1042 | "hex-to-binary": { 1043 | "version": "1.0.1", 1044 | "resolved": "https://registry.npmjs.org/hex-to-binary/-/hex-to-binary-1.0.1.tgz", 1045 | "integrity": "sha1-YcevAW/CK86pcE2fLpo46MfbuFQ=" 1046 | }, 1047 | "hmac-drbg": { 1048 | "version": "1.0.1", 1049 | "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", 1050 | "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", 1051 | "requires": { 1052 | "hash.js": "^1.0.3", 1053 | "minimalistic-assert": "^1.0.0", 1054 | "minimalistic-crypto-utils": "^1.0.1" 1055 | } 1056 | }, 1057 | "http-errors": { 1058 | "version": "1.8.1", 1059 | "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz", 1060 | "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==", 1061 | "requires": { 1062 | "depd": "~1.1.2", 1063 | "inherits": "2.0.4", 1064 | "setprototypeof": "1.2.0", 1065 | "statuses": ">= 1.5.0 < 2", 1066 | "toidentifier": "1.0.1" 1067 | } 1068 | }, 1069 | "iconv-lite": { 1070 | "version": "0.4.24", 1071 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", 1072 | "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", 1073 | "requires": { 1074 | "safer-buffer": ">= 2.1.2 < 3" 1075 | } 1076 | }, 1077 | "inherits": { 1078 | "version": "2.0.4", 1079 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1080 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1081 | }, 1082 | "ipaddr.js": { 1083 | "version": "1.9.1", 1084 | "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", 1085 | "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" 1086 | }, 1087 | "media-typer": { 1088 | "version": "0.3.0", 1089 | "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", 1090 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" 1091 | }, 1092 | "merge-descriptors": { 1093 | "version": "1.0.1", 1094 | "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", 1095 | "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" 1096 | }, 1097 | "methods": { 1098 | "version": "1.1.2", 1099 | "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", 1100 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" 1101 | }, 1102 | "mime": { 1103 | "version": "1.6.0", 1104 | "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", 1105 | "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" 1106 | }, 1107 | "mime-db": { 1108 | "version": "1.52.0", 1109 | "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", 1110 | "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" 1111 | }, 1112 | "mime-types": { 1113 | "version": "2.1.35", 1114 | "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", 1115 | "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", 1116 | "requires": { 1117 | "mime-db": "1.52.0" 1118 | } 1119 | }, 1120 | "minimalistic-assert": { 1121 | "version": "1.0.1", 1122 | "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", 1123 | "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" 1124 | }, 1125 | "minimalistic-crypto-utils": { 1126 | "version": "1.0.1", 1127 | "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", 1128 | "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=" 1129 | }, 1130 | "ms": { 1131 | "version": "2.0.0", 1132 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1133 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1134 | }, 1135 | "negotiator": { 1136 | "version": "0.6.3", 1137 | "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", 1138 | "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" 1139 | }, 1140 | "on-finished": { 1141 | "version": "2.3.0", 1142 | "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", 1143 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", 1144 | "requires": { 1145 | "ee-first": "1.1.1" 1146 | } 1147 | }, 1148 | "parseurl": { 1149 | "version": "1.3.3", 1150 | "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", 1151 | "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" 1152 | }, 1153 | "path-to-regexp": { 1154 | "version": "0.1.7", 1155 | "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", 1156 | "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" 1157 | }, 1158 | "proxy-addr": { 1159 | "version": "2.0.7", 1160 | "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", 1161 | "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", 1162 | "requires": { 1163 | "forwarded": "0.2.0", 1164 | "ipaddr.js": "1.9.1" 1165 | } 1166 | }, 1167 | "qs": { 1168 | "version": "6.9.7", 1169 | "resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz", 1170 | "integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==" 1171 | }, 1172 | "range-parser": { 1173 | "version": "1.2.1", 1174 | "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", 1175 | "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" 1176 | }, 1177 | "raw-body": { 1178 | "version": "2.4.3", 1179 | "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.3.tgz", 1180 | "integrity": "sha512-UlTNLIcu0uzb4D2f4WltY6cVjLi+/jEN4lgEUj3E04tpMDpUlkBo/eSn6zou9hum2VMNpCCUone0O0WeJim07g==", 1181 | "requires": { 1182 | "bytes": "3.1.2", 1183 | "http-errors": "1.8.1", 1184 | "iconv-lite": "0.4.24", 1185 | "unpipe": "1.0.0" 1186 | } 1187 | }, 1188 | "safe-buffer": { 1189 | "version": "5.2.1", 1190 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1191 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1192 | }, 1193 | "safer-buffer": { 1194 | "version": "2.1.2", 1195 | "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", 1196 | "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" 1197 | }, 1198 | "send": { 1199 | "version": "0.17.2", 1200 | "resolved": "https://registry.npmjs.org/send/-/send-0.17.2.tgz", 1201 | "integrity": "sha512-UJYB6wFSJE3G00nEivR5rgWp8c2xXvJ3OPWPhmuteU0IKj8nKbG3DrjiOmLwpnHGYWAVwA69zmTm++YG0Hmwww==", 1202 | "requires": { 1203 | "debug": "2.6.9", 1204 | "depd": "~1.1.2", 1205 | "destroy": "~1.0.4", 1206 | "encodeurl": "~1.0.2", 1207 | "escape-html": "~1.0.3", 1208 | "etag": "~1.8.1", 1209 | "fresh": "0.5.2", 1210 | "http-errors": "1.8.1", 1211 | "mime": "1.6.0", 1212 | "ms": "2.1.3", 1213 | "on-finished": "~2.3.0", 1214 | "range-parser": "~1.2.1", 1215 | "statuses": "~1.5.0" 1216 | }, 1217 | "dependencies": { 1218 | "ms": { 1219 | "version": "2.1.3", 1220 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1221 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" 1222 | } 1223 | } 1224 | }, 1225 | "serve-static": { 1226 | "version": "1.14.2", 1227 | "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.2.tgz", 1228 | "integrity": "sha512-+TMNA9AFxUEGuC0z2mevogSnn9MXKb4fa7ngeRMJaaGv8vTwnIEkKi+QGvPt33HSnf8pRS+WGM0EbMtCJLKMBQ==", 1229 | "requires": { 1230 | "encodeurl": "~1.0.2", 1231 | "escape-html": "~1.0.3", 1232 | "parseurl": "~1.3.3", 1233 | "send": "0.17.2" 1234 | } 1235 | }, 1236 | "setprototypeof": { 1237 | "version": "1.2.0", 1238 | "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", 1239 | "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" 1240 | }, 1241 | "statuses": { 1242 | "version": "1.5.0", 1243 | "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", 1244 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" 1245 | }, 1246 | "toidentifier": { 1247 | "version": "1.0.1", 1248 | "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", 1249 | "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" 1250 | }, 1251 | "type-is": { 1252 | "version": "1.6.18", 1253 | "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", 1254 | "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", 1255 | "requires": { 1256 | "media-typer": "0.3.0", 1257 | "mime-types": "~2.1.24" 1258 | } 1259 | }, 1260 | "uniqid": { 1261 | "version": "5.4.0", 1262 | "resolved": "https://registry.npmjs.org/uniqid/-/uniqid-5.4.0.tgz", 1263 | "integrity": "sha512-38JRbJ4Fj94VmnC7G/J/5n5SC7Ab46OM5iNtSstB/ko3l1b5g7ALt4qzHFgGciFkyiRNtDXtLNb+VsxtMSE77A==" 1264 | }, 1265 | "unpipe": { 1266 | "version": "1.0.0", 1267 | "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", 1268 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" 1269 | }, 1270 | "utils-merge": { 1271 | "version": "1.0.1", 1272 | "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", 1273 | "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" 1274 | }, 1275 | "vary": { 1276 | "version": "1.1.2", 1277 | "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", 1278 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" 1279 | } 1280 | } 1281 | } 1282 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "@types/node": "^17.0.23", 4 | "axios": "^0.26.1", 5 | "cls.js": "^1.5.0", 6 | "elliptic": "^6.5.4", 7 | "express": "^4.17.3", 8 | "hex-to-bin": "^1.0.1", 9 | "hex-to-binary": "^1.0.1", 10 | "uniqid": "^5.4.0" 11 | }, 12 | "devDependencies": { 13 | "@types/elliptic": "^6.4.14", 14 | "@types/express": "^4.17.13", 15 | "@types/uniqid": "^5.3.2", 16 | "@types/uuid": "^8.3.4" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Visit https://aka.ms/tsconfig.json to read more about this file */ 4 | 5 | /* Projects */ 6 | // "incremental": true, /* Enable incremental compilation */ 7 | // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ 8 | // "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */ 9 | // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ 10 | // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ 11 | // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ 12 | 13 | /* Language and Environment */ 14 | "target": "ES2022", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ 15 | // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ 16 | // "jsx": "preserve", /* Specify what JSX code is generated. */ 17 | // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ 18 | // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ 19 | // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ 20 | // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ 21 | // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ 22 | // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ 23 | // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ 24 | // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ 25 | 26 | /* Modules */ 27 | "module": "CommonJS", /* Specify what module code is generated. */ 28 | // "rootDir": "./", /* Specify the root folder within your source files. */ 29 | // "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ 30 | // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ 31 | // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ 32 | // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ 33 | // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ 34 | // "types": [], /* Specify type package names to be included without being referenced in a source file. */ 35 | // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ 36 | // "resolveJsonModule": true, /* Enable importing .json files */ 37 | // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ 38 | 39 | /* JavaScript Support */ 40 | // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */ 41 | // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ 42 | // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ 43 | 44 | /* Emit */ 45 | // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ 46 | // "declarationMap": true, /* Create sourcemaps for d.ts files. */ 47 | // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ 48 | // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ 49 | // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ 50 | // "outDir": "./", /* Specify an output folder for all emitted files. */ 51 | // "removeComments": true, /* Disable emitting comments. */ 52 | // "noEmit": true, /* Disable emitting files from a compilation. */ 53 | // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ 54 | // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ 55 | // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ 56 | // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ 57 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 58 | // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ 59 | // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ 60 | // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ 61 | // "newLine": "crlf", /* Set the newline character for emitting files. */ 62 | // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ 63 | // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ 64 | // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ 65 | // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ 66 | // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ 67 | // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ 68 | 69 | /* Interop Constraints */ 70 | // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ 71 | // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ 72 | "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */ 73 | // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ 74 | "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ 75 | 76 | /* Type Checking */ 77 | "strict": true, /* Enable all strict type-checking options. */ 78 | // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ 79 | // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ 80 | // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ 81 | // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ 82 | // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ 83 | // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ 84 | // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ 85 | // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ 86 | // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ 87 | // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ 88 | // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ 89 | // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ 90 | // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ 91 | // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ 92 | // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ 93 | // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ 94 | // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ 95 | // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ 96 | 97 | /* Completeness */ 98 | // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ 99 | "skipLibCheck": true /* Skip type checking all .d.ts files. */ 100 | } 101 | } 102 | --------------------------------------------------------------------------------