├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .npmrc ├── .prettierrc ├── BOOTSTRAP_FILES.md ├── EVENT_EMITTERS.md ├── LICENSE.md ├── OPTIONAL_PARAMETERS.md ├── README.md ├── dist ├── analyzers │ ├── block-analyzer.d.ts │ ├── block-analyzer.js │ └── block-analyzer.js.map ├── common │ ├── constants.d.ts │ ├── constants.js │ ├── constants.js.map │ ├── profiles.d.ts │ ├── profiles.js │ └── profiles.js.map ├── core │ ├── api.d.ts │ ├── api.js │ ├── api.js.map │ ├── mesh.d.ts │ ├── mesh.js │ ├── mesh.js.map │ ├── node.d.ts │ ├── node.js │ ├── node.js.map │ ├── syncer.d.ts │ ├── syncer.js │ └── syncer.js.map ├── delegates │ ├── rpc-delegate.d.ts │ ├── rpc-delegate.js │ └── rpc-delegate.js.map ├── helpers │ ├── block-helper.d.ts │ ├── block-helper.js │ └── block-helper.js.map ├── neo.d.ts ├── neo.js ├── neo.js.map ├── storages │ ├── memory-storage.d.ts │ ├── memory-storage.js │ ├── memory-storage.js.map │ ├── mongodb-storage.d.ts │ ├── mongodb-storage.js │ ├── mongodb-storage.js.map │ └── mongodb │ │ ├── block-dao.d.ts │ │ ├── block-dao.js │ │ ├── block-dao.js.map │ │ ├── block-meta-dao.d.ts │ │ ├── block-meta-dao.js │ │ ├── block-meta-dao.js.map │ │ ├── schemas.d.ts │ │ ├── schemas.js │ │ ├── schemas.js.map │ │ ├── transaction-meta-dao.d.ts │ │ ├── transaction-meta-dao.js │ │ ├── transaction-meta-dao.js.map │ │ ├── utils.d.ts │ │ ├── utils.js │ │ └── utils.js.map └── validators │ ├── endpoint-validator.d.ts │ ├── endpoint-validator.js │ ├── endpoint-validator.js.map │ ├── mongodb-validator.d.ts │ ├── mongodb-validator.js │ ├── mongodb-validator.js.map │ ├── neo-validator.d.ts │ ├── neo-validator.js │ ├── neo-validator.js.map │ ├── rpc-validator.d.ts │ ├── rpc-validator.js │ └── rpc-validator.js.map ├── docs ├── assets │ ├── css │ │ ├── main.css │ │ └── main.css.map │ ├── images │ │ ├── icons.png │ │ ├── icons@2x.png │ │ ├── widgets.png │ │ └── widgets@2x.png │ └── js │ │ ├── main.js │ │ └── search.js ├── classes │ ├── _analyzers_block_analyzer_.blockanalyzer.html │ ├── _core_api_.api.html │ ├── _core_mesh_.mesh.html │ ├── _core_node_.node.html │ ├── _core_syncer_.syncer.html │ ├── _delegates_rpc_delegate_.rpcdelegate.html │ ├── _helpers_block_helper_.blockhelper.html │ ├── _neo_.neo.html │ ├── _storages_memory_storage_.memorystorage.html │ ├── _storages_mongodb_block_dao_.blockdao.html │ ├── _storages_mongodb_block_meta_dao_.blockmetadao.html │ ├── _storages_mongodb_storage_.mongodbstorage.html │ ├── _storages_mongodb_transaction_meta_dao_.transactionmetadao.html │ ├── _storages_mongodb_utils_.mongodbutils.html │ ├── _validators_endpoint_validator_.endpointvalidator.html │ ├── _validators_mongodb_validator_.mongodbvalidator.html │ ├── _validators_neo_validator_.neovalidator.html │ └── _validators_rpc_validator_.rpcvalidator.html ├── globals.html ├── index.html ├── interfaces │ ├── _analyzers_block_analyzer_.blockanalyzeroptions.html │ ├── _core_api_.apioptions.html │ ├── _core_api_.storageinsertpayload.html │ ├── _core_mesh_.meshoptions.html │ ├── _core_node_.nodemeta.html │ ├── _core_node_.nodeoptions.html │ ├── _core_syncer_.synceroptions.html │ ├── _neo_.neooptions.html │ ├── _storages_memory_storage_.blockitem.html │ ├── _storages_memory_storage_.memorystorageoptions.html │ └── _storages_mongodb_storage_.mongodbstorageoptions.html └── modules │ ├── _analyzers_block_analyzer_.html │ ├── _common_constants_.html │ ├── _common_profiles_.html │ ├── _core_api_.html │ ├── _core_mesh_.html │ ├── _core_node_.html │ ├── _core_syncer_.html │ ├── _delegates_rpc_delegate_.html │ ├── _helpers_block_helper_.html │ ├── _neo_.html │ ├── _storages_memory_storage_.html │ ├── _storages_mongodb_block_dao_.html │ ├── _storages_mongodb_block_meta_dao_.html │ ├── _storages_mongodb_schemas_.html │ ├── _storages_mongodb_storage_.html │ ├── _storages_mongodb_transaction_meta_dao_.html │ ├── _storages_mongodb_utils_.html │ ├── _validators_endpoint_validator_.html │ ├── _validators_mongodb_validator_.html │ ├── _validators_neo_validator_.html │ └── _validators_rpc_validator_.html ├── package-lock.json ├── package.json ├── src ├── analyzers │ └── block-analyzer.ts ├── common │ ├── constants.ts │ └── profiles.ts ├── core │ ├── api.ts │ ├── mesh.ts │ ├── node.ts │ └── syncer.ts ├── delegates │ └── rpc-delegate.ts ├── helpers │ └── block-helper.ts ├── neo.ts ├── storages │ ├── memory-storage.ts │ ├── mongodb-storage.ts │ └── mongodb │ │ ├── block-dao.ts │ │ ├── block-meta-dao.ts │ │ ├── schemas.ts │ │ ├── transaction-meta-dao.ts │ │ └── utils.ts └── validators │ ├── endpoint-validator.ts │ ├── mongodb-validator.ts │ ├── neo-validator.ts │ └── rpc-validator.ts ├── test └── test.js ├── tsconfig.json └── tslint.json /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to `neo-js` 2 | 3 | 1. [Getting Involved](#getting-involved) 4 | 1. [Questions and Discussion](#questions-and-discussion) 5 | 1. [Core Style Guide](#core-style-guide) 6 | 1. [Pull Request Process](#pull-request-process) 7 | 1. [Code of Conduct](#code-of-conduct) 8 | 9 | ## Getting Involved 10 | 11 | We're always looking for help identifying bugs, writing and reducing test cases, and improving documentation. Whether it is new feature or code improvement, anything passing our guidelines will be considered. 12 | 13 | When contributing to this repository, please first discuss the change you wish to make via issue, email, or any other method with the owners of this repository before making a change. 14 | 15 | ## Questions and Discussion 16 | 17 | Please start by search the issue tracker as your issue may have already been discussed or fixed. If it is something that is not yet discussed, please file a new issue in the issue tracker. 18 | 19 | You may also use the [official community chat](https://discord.gg/R8v48YA) and join the software discussion on its developer channel. 20 | 21 | ## Core Style Guide 22 | 23 | `neo-js` is current under rapid developments and improvements, please follow core contributors' recommendation when raised. 24 | 25 | Before submitted a pull request, ensure you tested your code against ESLint rules in the project: 26 | 27 | ```js 28 | npm run format && npm run lint 29 | ``` 30 | 31 | ## Pull Request Process 32 | 33 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build. 34 | 1. Update the `README.md` with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters. 35 | 1. Pull requests are made against feature branches and the develop branch. 36 | 1. You may merge the Pull Request in once you have the sign-off of a developer on the project. 37 | 38 | ## Code of Conduct 39 | 40 | ### Our Pledge 41 | 42 | In the interest of fostering an open and welcoming environment, we as 43 | contributors and maintainers pledge to making participation in our project and 44 | our community a harassment-free experience for everyone, regardless of age, body 45 | size, disability, ethnicity, gender identity and expression, level of experience, 46 | nationality, personal appearance, race, religion, or sexual identity and 47 | orientation. 48 | 49 | ### Our Standards 50 | 51 | Examples of behavior that contributes to creating a positive environment 52 | include: 53 | 54 | * Using welcoming and inclusive language 55 | * Being respectful of differing viewpoints and experiences 56 | * Gracefully accepting constructive criticism 57 | * Focusing on what is best for the community 58 | * Showing empathy towards other community members 59 | 60 | Examples of unacceptable behavior by participants include: 61 | 62 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 63 | * Trolling, insulting/derogatory comments, and personal or political attacks 64 | * Public or private harassment 65 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 66 | * Other conduct which could reasonably be considered inappropriate in a professional setting 67 | 68 | ### Our Responsibilities 69 | 70 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 71 | 72 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 73 | 74 | ### Scope 75 | 76 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail 77 | address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 78 | 79 | ### Enforcement 80 | 81 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [INSERT EMAIL ADDRESS]. All complaints will be reviewed and investigated and will result in a response that 82 | is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 83 | 84 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 85 | 86 | ### Attribution 87 | 88 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 89 | available at [http://contributor-covenant.org/version/1/4][version] 90 | 91 | [homepage]: http://contributor-covenant.org 92 | [version]: http://contributor-covenant.org/version/1/4/ 93 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Context (Environment) 4 | 5 | * **`neo-js` Version**: 6 | * **`node` Version**: 7 | * **Operation System**: 8 | * **MongoDB Version** (if applicable): 9 | 10 | ## Expected behavior 11 | 12 | ## Actual behavior 13 | 14 | ## Steps to reproduce the behavior 15 | 16 | 1. 17 | 1. 18 | 1. 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Description 4 | 5 | 6 | ## Motivation and Context 7 | 8 | 9 | 10 | ## How Has This Been Tested? 11 | 12 | 13 | 14 | 15 | ## Types of changes: 16 | 17 | 18 | - [ ] Bug fix (non-breaking change which fixes an issue) 19 | - [ ] New feature (non-breaking change which adds functionality) 20 | - [ ] Breaking change (fix or feature that would cause existing functionality to change) 21 | 22 | ## Checklist: 23 | 24 | 25 | 26 | - [ ] My code follows the code style of this project. 27 | - [ ] My change requires a change to the documentation. 28 | - [ ] I have updated the documentation accordingly. 29 | - [ ] I have read the **CONTRIBUTING** document. 30 | - [ ] I have added tests to cover my changes. 31 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .examples 3 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | tag-version-prefix="" 2 | message="Version bump to %s" 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 240, 3 | "singleQuote": true, 4 | "trailingComma": "es5", 5 | "semi": false, 6 | "arrowParens": "always" 7 | } 8 | -------------------------------------------------------------------------------- /BOOTSTRAP_FILES.md: -------------------------------------------------------------------------------- 1 | # Blockchain Bootstrap Files 2 | 3 | MongoDB bootstrap files comes in 2 flavors: 4 | 5 | * [`mongoexport`](https://docs.mongodb.com/manual/reference/program/mongoexport/) 6 | * [`mongodump`](https://docs.mongodb.com/manual/reference/program/mongodump/) 7 | 8 | ## `mongoexport` 9 | 10 | Raw JSON file exports, human readable and can be imported into any specified database and collection. 11 | 12 | After extracted, you can choose to import JSON objects manually (through `db.collection.insert()`) or via `mongoimport`: 13 | 14 | * Example usage: 15 | 16 | ``` 17 | mongoimport -d DATABASE_NAME -c COLLECTION_NAME --file IMPORT_FILE.json 18 | ``` 19 | 20 | ### Mainnet block 1 - 1,000,000 21 | 22 | * Date Created: 2018-12-04 23 | * Filename: `neo_mainnet_blocks_1_1000000.7z` 24 | * File Size: 0.47GB 25 | * URL: https://drive.google.com/file/d/1hJxbJdVEX5jAViyZ-cYmlrZOmhcrhWtv/view?usp=sharing 26 | * MD5: `49db7bd858915ea846c4aa517589cb76` 27 | * SHA256: `a30b8660d9c014bed1c86b2e6dd95e35a87628c4e247213424850ce019c2a8c3` 28 | 29 | ### Mainnet block 1,000,001 - 2,000,000 30 | 31 | * Date Created: 2018-12-04 32 | * Filename: `neo_mainnet_blocks_1000001_2000000.7z` 33 | * File Size: 1.79GB 34 | * URL: https://drive.google.com/file/d/1njUMFSN9nI9AYmq2btFSgG2_Vvxi-SRs/view?usp=sharing 35 | * MD5: `dfda4757622c69964da8c2274175f29c` 36 | * SHA256: `ae93993e4fdcebde4b1dbe1c71066c8e50933355d3aad9c6aa03b82c9e803fbc` 37 | 38 | ### Mainnet block 2,000,001 - 2,500,000 39 | 40 | * Date Created: 2018-12-04 41 | * Filename: `neo_mainnet_blocks_2000001_2500000.7z` 42 | * File Size: 1.35GB 43 | * URL: https://drive.google.com/file/d/1uQ_hYzoO1RGjoXXV7sgL19yYyvYh7TtB/view?usp=sharing 44 | * MD5: `d552da04c12f3191210337b9345566d8` 45 | * SHA256: `b053eff2eb9e308e82741dcfe0de95ee3de3451913808a46b6a7258e7d7889fb` 46 | 47 | ### Mainnet block 2,500,001 - 3,000,000 48 | 49 | * Date Created: 2018-12-04 50 | * Filename: `neo_mainnet_blocks_2500001_3000000.7z` 51 | * File Size: 1.30GB 52 | * URL: https://drive.google.com/file/d/1QSoRo09ElwqDHQ2-OoQRLIjNjg3dDwqf/view?usp=sharing 53 | * MD5: `3b09948c2c755969df4798efdf6308af` 54 | * SHA256: `f781c4eda2295fc4b46c99cd3d36d28ac5a4a4b6a1adaad54bbba032ffd137fc` 55 | 56 |   57 | 58 | ## `mongodump` 59 | 60 | MongoDB archive file that can be used to restore an entire database via `mongorestore`. 61 | 62 | * Example usage: 63 | 64 | ``` 65 | mongorestore --gzip --archive=BACKUP_FILE.archive.gz 66 | ``` 67 | 68 | ### Mainnet up to block 2,980,149 69 | 70 | * Date Created: 2018-11-19 71 | * Database name: `neo_mainnet` 72 | * Collection names: 73 | * Block: `blocks` 74 | * Block range: from 1 to 2,980,149 75 | * Filename: `neo_mainnet_blocks_2980149.archive.gz` 76 | * File size: 6.7GB 77 | * URL: https://drive.google.com/file/d/1WSqwHs9imjD-5Kf03Mx23iCy_ABtdV5r/view?usp=sharing 78 | * MD5: `6ee692dabc51af2531b15048fd3ede23` 79 | * SHA256: `dc0c856959fd9ee28d412f007c226623742a4af987b756f93503ba987f247775` 80 | -------------------------------------------------------------------------------- /EVENT_EMITTERS.md: -------------------------------------------------------------------------------- 1 | # Event Emitters 2 | 3 | Events emitters per class and possible payload properties. 4 | 5 | ### `neo` 6 | 7 | N/A 8 | 9 |   10 | 11 | ### `core/api` 12 | 13 | #### `ready` 14 | 15 | ```js 16 | null 17 | ``` 18 | 19 | #### `storage:insert` 20 | 21 | ```js 22 | { 23 | method: string 24 | result: any 25 | } 26 | ``` 27 | 28 |   29 | 30 | ### `core/mesh` 31 | 32 | #### `ready` 33 | 34 | ```js 35 | null 36 | ``` 37 | 38 |   39 | 40 | ### `core/syncer` 41 | 42 | #### `start` 43 | 44 | ```js 45 | null 46 | ``` 47 | 48 | #### `stop` 49 | 50 | ```js 51 | null 52 | ``` 53 | 54 | #### `query:worker:complete` 55 | 56 | ```js 57 | { 58 | isSuccess: boolean 59 | } 60 | ``` 61 | 62 | #### `blockVerification:init` 63 | 64 | ```js 65 | null 66 | ``` 67 | 68 | #### `blockVerification:complete` 69 | 70 | ```js 71 | { 72 | isSkipped: boolean 73 | } 74 | ``` 75 | 76 | #### `blockVerification:missingBlocks` 77 | 78 | ```js 79 | { 80 | count: number 81 | } 82 | ``` 83 | 84 | #### `blockVerification:excessiveBlocks` 85 | 86 | ```js 87 | { 88 | count: number 89 | } 90 | ``` 91 | 92 | #### `storeBlock:init` 93 | 94 | ```js 95 | { 96 | height: number 97 | } 98 | ``` 99 | 100 | #### `storeBlock:complete` 101 | 102 | ```js 103 | { 104 | isSuccess?: boolean 105 | isSkipped?: boolean 106 | height: number 107 | } 108 | ``` 109 | 110 | #### `upToDate` 111 | 112 | ```js 113 | null 114 | ``` 115 | 116 |   117 | 118 | ### `core/node` 119 | 120 | #### `query:init` 121 | 122 | ```js 123 | { 124 | method: string 125 | params: object 126 | id: string 127 | } 128 | ``` 129 | 130 | #### `query:complete` 131 | 132 | ```js 133 | { 134 | isSuccess: boolean 135 | method: string 136 | latency?: number 137 | blockHeight?: number 138 | userAgent?: string 139 | error?: object 140 | } 141 | ``` 142 | 143 |   144 | 145 | ### `storages/memory-storage` 146 | 147 | #### `ready` 148 | 149 | ```js 150 | null 151 | ``` 152 | 153 |   154 | 155 | ### `storages/mongodb-storage` 156 | 157 | #### `ready` 158 | 159 | ```js 160 | null 161 | ``` 162 | 163 | #### `reviewIndexes:init` 164 | 165 | ```js 166 | null 167 | ``` 168 | 169 | #### `reviewIndexes:complete` 170 | 171 | ```js 172 | { 173 | isSuccess: boolean 174 | } 175 | ``` 176 | 177 |   178 | 179 | ### `analyzers/block-meta-analyzer` 180 | 181 | #### `start` 182 | 183 | ```js 184 | null 185 | ``` 186 | 187 | #### `stop` 188 | 189 | ```js 190 | null 191 | ``` 192 | 193 | #### `query:worker:complete` 194 | 195 | ```js 196 | { 197 | isSuccess: boolean 198 | task: object 199 | } 200 | ``` 201 | 202 | #### `blockMetaVerification:init` 203 | 204 | ```js 205 | null 206 | ``` 207 | 208 | #### `blockMetaVerification:complete` 209 | 210 | ```js 211 | { 212 | isSuccess?: boolean 213 | isSkipped?: boolean 214 | } 215 | ``` 216 | 217 | #### `blockMetaVerification:blockMetas:missing` 218 | 219 | ```js 220 | { 221 | count: number 222 | } 223 | ``` 224 | 225 | #### `blockMetaVerification:blockMetas:legacy` 226 | 227 | ```js 228 | { 229 | count: number 230 | } 231 | ``` 232 | 233 | #### `blockMetaVerification:transactionMetas:legacy` 234 | 235 | ```js 236 | { 237 | metaCount: number 238 | } 239 | ``` 240 | 241 | #### `upToDate` 242 | 243 | ```js 244 | null 245 | ``` 246 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2018 City Of Zion 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /OPTIONAL_PARAMETERS.md: -------------------------------------------------------------------------------- 1 | # Optional Parameters 2 | 3 | Possible options and default values. 4 | 5 | ### `neo` 6 | 7 | ```js 8 | const neoOptions = { 9 | network: 'testnet', 10 | storageType: undefined, 11 | endpoints: undefined, 12 | enableSyncer: true, 13 | enableBlockAnalyzer: false, 14 | nodeOptions: undefined, 15 | meshOptions: undefined, 16 | storageOptions: undefined, 17 | apiOptions: undefined, 18 | syncerOptions: undefined, 19 | blockMetaAnalyzerOptions: undefined, 20 | loggerOptions: {}, 21 | } 22 | ``` 23 | 24 | ### `core/api` 25 | 26 | ```js 27 | const apiOptions = { 28 | insertToStorage: true, 29 | checkReadyIntervalMs: 200, 30 | loggerOptions: {}, 31 | } 32 | ``` 33 | 34 | ### `core/mesh` 35 | 36 | ```js 37 | const meshOptions = { 38 | startBenchmarkOnInit: true, 39 | toFetchUserAgent: true, 40 | benchmarkIntervalMs: 2000, 41 | fetchMissingUserAgentIntervalMs: 5000, 42 | refreshUserAgentIntervalMs: 5 * 60 * 1000, 43 | minActiveNodesRequired: 2, 44 | pendingRequestsThreshold: 5, 45 | loggerOptions: {}, 46 | } 47 | ``` 48 | 49 | ### `core/syncer` 50 | 51 | ```js 52 | const syncerOptions = { 53 | minHeight: 1, 54 | maxHeight: undefined, 55 | blockRedundancy: 1, 56 | checkRedundancyBeforeStoreBlock: true, 57 | startOnInit: true, 58 | toSyncIncremental: true, 59 | toSyncForMissingBlocks: true, 60 | toPruneRedundantBlocks: true, 61 | storeQueueConcurrency: 30, 62 | pruneQueueConcurrency: 10, 63 | enqueueBlockIntervalMs: 5000, 64 | verifyBlocksIntervalMs: 1 * 60 * 1000, 65 | maxStoreQueueLength: 1000, 66 | retryEnqueueDelayMs: 5000, 67 | standardEnqueueBlockPriority: 5, 68 | retryEnqueueBlockPriority: 3, 69 | missingEnqueueStoreBlockPriority: 1, 70 | enqueuePruneBlockPriority: 5, 71 | maxPruneChunkSize: 1000, 72 | loggerOptions: {}, 73 | } 74 | ``` 75 | 76 | ### `core/node` 77 | 78 | ```js 79 | const nodeOptions = { 80 | toLogReliability: false, 81 | truncateRequestLogIntervalMs: 30 * 1000, 82 | requestLogTtl: 5 * 60 * 1000, // In milliseconds 83 | timeout: 30000, 84 | loggerOptions: {}, 85 | } 86 | ``` 87 | 88 | ### `storages/memory-storage` 89 | 90 | ```js 91 | const memoryStorageOptions = { 92 | loggerOptions: {}, 93 | } 94 | ``` 95 | 96 | ### `storages/mongodb-storage` 97 | 98 | ```js 99 | const mongodbStorageOptions = { 100 | connectOnInit: true, 101 | reviewIndexesOnConnect: false, 102 | userAgent: 'Unknown', 103 | collectionNames: { 104 | blocks: 'blocks', 105 | blockMetas: 'block_metas', 106 | transactionMetas: 'transaction_metas', 107 | }, 108 | loggerOptions: {}, 109 | } 110 | ``` 111 | 112 | ### `analyzers/block-meta-analyzer` 113 | 114 | ```js 115 | const blockMetaAnalyzerOptions = { 116 | minHeight: 1, 117 | maxHeight: undefined, 118 | startOnInit: true, 119 | toEvaluateTransactions: true, 120 | toEvaluateAssets: false, 121 | blockQueueConcurrency: 5, 122 | transactionQueueConcurrency: 10, 123 | enqueueEvaluateBlockIntervalMs: 5 * 1000, 124 | verifyBlocksIntervalMs: 30 * 1000, 125 | maxBlockQueueLength: 30 * 1000, 126 | maxTransactionQueueLength: 100 * 1000, 127 | standardEvaluateBlockPriority: 5, 128 | missingEvaluateBlockPriority: 3, 129 | legacyEvaluateBlockPriority: 3, 130 | standardEvaluateTransactionPriority: 5, 131 | missingEvaluateTransactionPriority: 5, 132 | legacyEvaluateTransactionPriority: 5, 133 | loggerOptions: {}, 134 | } 135 | ``` 136 | 137 | ### `Logger` 138 | 139 | ```js 140 | const loggerOptions = { 141 | level: 'warn', // silent | error | warn | info | debug | trace 142 | displayTimestamp: true, 143 | displayName: true, 144 | displayLevel: true, 145 | useLevelInitial: false, 146 | useLocalTime: false, 147 | timestampFormat: 'YYYY-MM-DD HH:mm:ss.SSS' 148 | } 149 | ``` 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | City of Zion logo 6 |

7 | 8 |

9 | neo-js 10 |

11 | 12 |

13 | Running NEO blockchain full node with Node.js and MongoDB. 14 |

15 | 16 |

17 | 18 | npm version 19 | 20 |

21 | 22 | ## Overview 23 | 24 | `neo-js` package is designed to interface with the NEO blockchain in a number of different ways that are configured by options that are used to initialize a node. A few examples of these different interaction mechanics are defined in the quickstart below as well as in the examples. 25 | 26 | **This is not a SDK library for interacting with NEO blockchain. You are looking for [`neon-js`](https://github.com/cityofzion/neon-js).** 27 | 28 | ## Getting Started 29 | 30 | ### Preparations 31 | 32 | Currently this module only support MongoDB for synchronizing the blockchain. You are expect to be connected to an 33 | instance of MongoDB 3.2+ to use most of its features. 34 | 35 | ### System Recommendations 36 | 37 | * NodeJS 8+ 38 | * MongoDB 3.2+ 39 | 40 | ## Installation 41 | 42 | Install the package using: 43 | 44 | ```bash 45 | $ npm install --save @cityofzion/neo-js 46 | ``` 47 | 48 | Alternatively, to access to the latest available code, you can reference to the git repository directly: 49 | 50 | ```bash 51 | $ npm install --save git://github.com/CityOfZion/neo-js.git#develop 52 | ``` 53 | 54 | ## Quick Start 55 | 56 | More comprehensive examples can be found at [`neo-js-examples`](https://github.com/rockacola/neo-js-examples) repository. 57 | 58 | ```js 59 | const Neo = require('@cityofzion/neo-js').Neo 60 | ``` 61 | 62 | To create a new blockchain instance: 63 | 64 | ```js 65 | // Create a neo instances to interface with RPC methods 66 | const testnetNeo = new Neo({ network: 'testnet' }) 67 | 68 | // Wait for mesh to be ready before attempt to fetch block information 69 | testnetNeo.mesh.on('ready', () => { 70 | testnetNeo.api.getBlockCount() 71 | .then((res) => { 72 | console.log('Testnet getBlockCount:', res) 73 | }) 74 | }) 75 | 76 | // To connect to the mainnet: 77 | const mainnetNeo = new Neo({ network: 'mainnet' }) 78 | 79 | mainnetNeo.mesh.on('ready', () => { 80 | mainnetNeo.api.getBlock(1000) 81 | .then((res) => { 82 | console.log('Mainnet getBlock(1000).hash:', res.hash) 83 | }) 84 | }) 85 | ``` 86 | 87 | This will create a new node instance and configure it to sync the blockchain to the defined mongoDB collections: 88 | 89 | ```js 90 | const options = { 91 | network: 'testnet', 92 | storageType: 'mongodb', 93 | storageOptions: { 94 | connectionString: 'mongodb://localhost/neo_testnet', 95 | }, 96 | } 97 | 98 | // Create a neo instance 99 | const neo = new Neo(options) 100 | 101 | // Get block height 102 | neo.storage.on('ready', () => { 103 | neo.storage.getHighestBlockHeight() 104 | .then((res) => { 105 | console.log('Block height:', res) 106 | }) 107 | }) 108 | ``` 109 | 110 | ## Documentation 111 | 112 | Documentation for the project can be found at: 113 | 114 | * [http://cityofzion.io/neo-js/](http://cityofzion.io/neo-js/) 115 | 116 | You can find more code examples at repository: 117 | 118 | * [https://github.com/rockacola/neo-js-examples](https://github.com/rockacola/neo-js-examples) 119 | 120 | ## Blockchain Bootstrap Files 121 | 122 | [_Please refer to Bootstrap Files document_](https://github.com/CityOfZion/neo-js/blob/master/BOOTSTRAP_FILES.md) 123 | 124 | ## Options 125 | 126 | [_Please refer to Optional Parameters document_](https://github.com/CityOfZion/neo-js/blob/master/OPTIONAL_PARAMETERS.md) 127 | 128 | ## Events 129 | 130 | [_Please refer to Event Emitters document_](https://github.com/CityOfZion/neo-js/blob/master/EVENT_EMITTERS.md) 131 | 132 | ## Contribution 133 | 134 | `neo-js` always encourages community code contribution. Before contributing please read the [contributor guidelines](https://github.com/CityOfZion/neo-js/blob/master/.github/CONTRIBUTING.md) and search the issue tracker as your issue may have already been discussed or fixed. To contribute, fork `neo-js`, commit your changes and submit a pull request. 135 | 136 | By contributing to `neo-js`, you agree that your contributions will be licensed under its MIT license. 137 | 138 | ## License 139 | 140 | * Open-source [MIT](https://github.com/CityOfZion/neo-js/blob/master/LICENSE.md). 141 | * Authors: 142 | * [@lllwvlvwlll](https://github.com/lllwvlvwlll) 143 | * [@rockacola](https://github.com/rockacola) 144 | -------------------------------------------------------------------------------- /dist/analyzers/block-analyzer.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { EventEmitter } from 'events'; 3 | import { LoggerOptions } from 'node-log-it'; 4 | import { MemoryStorage } from '../storages/memory-storage'; 5 | import { MongodbStorage } from '../storages/mongodb-storage'; 6 | export interface BlockAnalyzerOptions { 7 | minHeight?: number; 8 | maxHeight?: number; 9 | startOnInit?: boolean; 10 | toEvaluateTransactions?: boolean; 11 | toEvaluateAssets?: boolean; 12 | blockQueueConcurrency?: number; 13 | transactionQueueConcurrency?: number; 14 | enqueueEvaluateBlockIntervalMs?: number; 15 | verifyBlocksIntervalMs?: number; 16 | maxBlockQueueLength?: number; 17 | maxTransactionQueueLength?: number; 18 | standardEvaluateBlockPriority?: number; 19 | missingEvaluateBlockPriority?: number; 20 | legacyEvaluateBlockPriority?: number; 21 | standardEvaluateTransactionPriority?: number; 22 | missingEvaluateTransactionPriority?: number; 23 | legacyEvaluateTransactionPriority?: number; 24 | loggerOptions?: LoggerOptions; 25 | } 26 | export declare class BlockAnalyzer extends EventEmitter { 27 | private BLOCK_META_API_LEVEL; 28 | private TRANSACTION_META_API_LEVEL; 29 | private _isRunning; 30 | private blockQueue; 31 | private transactionQueue; 32 | private blockWritePointer; 33 | private storage?; 34 | private options; 35 | private logger; 36 | private enqueueEvaluateBlockIntervalId?; 37 | private blockVerificationIntervalId?; 38 | private isVerifyingBlocks; 39 | constructor(storage?: MemoryStorage | MongodbStorage, options?: BlockAnalyzerOptions); 40 | isRunning(): boolean; 41 | start(): void; 42 | stop(): void; 43 | close(): void; 44 | private validateOptionalParameters; 45 | private getPriorityQueue; 46 | private initEvaluateBlock; 47 | private setBlockWritePointer; 48 | private initBlockVerification; 49 | private doBlockVerification; 50 | private verifyBlockMetas; 51 | private verifyTransactionMetas; 52 | private doEnqueueEvaluateBlock; 53 | private isReachedMaxHeight; 54 | private isReachedMaxQueueLength; 55 | private increaseBlockWritePointer; 56 | private enqueueEvaluateBlock; 57 | private evaluateBlock; 58 | private enqueueEvaluateTransaction; 59 | private enqueueEvaluateTransactionWithHeight; 60 | private evaluateTransaction; 61 | private getNumberArray; 62 | } 63 | -------------------------------------------------------------------------------- /dist/analyzers/block-analyzer.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"block-analyzer.js","sourceRoot":"","sources":["../../src/analyzers/block-analyzer.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,mCAAqC;AACrC,iCAAyD;AACzD,6CAAmD;AACnD,mCAAsE;AAGtE,0DAAqD;AAErD,MAAM,WAAW,GAAG,eAAe,CAAA;AACnC,MAAM,eAAe,GAAyB;IAC5C,SAAS,EAAE,CAAC;IACZ,SAAS,EAAE,SAAS;IACpB,WAAW,EAAE,IAAI;IACjB,sBAAsB,EAAE,IAAI;IAC5B,gBAAgB,EAAE,KAAK;IACvB,qBAAqB,EAAE,CAAC;IACxB,2BAA2B,EAAE,EAAE;IAC/B,8BAA8B,EAAE,CAAC,GAAG,IAAI;IACxC,sBAAsB,EAAE,EAAE,GAAG,IAAI;IACjC,mBAAmB,EAAE,EAAE,GAAG,IAAI;IAC9B,yBAAyB,EAAE,GAAG,GAAG,IAAI;IACrC,6BAA6B,EAAE,CAAC;IAChC,4BAA4B,EAAE,CAAC;IAC/B,2BAA2B,EAAE,CAAC;IAC9B,mCAAmC,EAAE,CAAC;IACtC,kCAAkC,EAAE,CAAC;IACrC,iCAAiC,EAAE,CAAC;IACpC,aAAa,EAAE,EAAE;CAClB,CAAA;AAuBD,MAAa,aAAc,SAAQ,qBAAY;IAiB7C,YAAY,OAAwC,EAAE,UAAgC,EAAE;QACtF,KAAK,EAAE,CAAA;QAdD,yBAAoB,GAAG,CAAC,CAAA;QACxB,+BAA0B,GAAG,CAAC,CAAA;QAC9B,eAAU,GAAG,KAAK,CAAA;QAGlB,sBAAiB,GAAW,CAAC,CAAA;QAM7B,sBAAiB,GAAG,KAAK,CAAA;QAM/B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QAGtB,IAAI,CAAC,OAAO,GAAG,cAAK,CAAC,EAAE,EAAE,eAAe,EAAE,OAAO,CAAC,CAAA;QAClD,IAAI,CAAC,0BAA0B,EAAE,CAAA;QAGjC,IAAI,CAAC,MAAM,GAAG,IAAI,oBAAM,CAAC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAA;QACjE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,qBAAsB,CAAC,CAAA;QAC5E,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,2BAA4B,CAAC,CAAA;QACxF,IAAI,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE;YAC5B,IAAI,CAAC,KAAK,EAAE,CAAA;SACb;QAED,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAA;IAC7C,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,UAAU,CAAA;IACxB,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,UAAU,EAAE;YACnB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAA;YACtD,OAAM;SACP;QAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE;YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAA;YAC9E,OAAM;SACP;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;QACxC,IAAI,CAAC,UAAU,GAAG,IAAI,CAAA;QACtB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAElB,IAAI,CAAC,iBAAiB,EAAE,CAAA;QACxB,IAAI,CAAC,qBAAqB,EAAE,CAAA;IAC9B,CAAC;IAED,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE;YACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAA;YAC/D,OAAM;SACP;QAED,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;QACvC,IAAI,CAAC,UAAU,GAAG,KAAK,CAAA;QACvB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QAEjB,aAAa,CAAC,IAAI,CAAC,8BAA+B,CAAC,CAAA;QACnD,aAAa,CAAC,IAAI,CAAC,2BAA4B,CAAC,CAAA;IAClD,CAAC;IAED,KAAK;QACH,IAAI,CAAC,IAAI,EAAE,CAAA;IACb,CAAC;IAEO,0BAA0B;IAElC,CAAC;IAEO,gBAAgB,CAAC,WAAmB;QAC1C,OAAO,qBAAa,CAAC,CAAC,IAAY,EAAE,QAAoB,EAAE,EAAE;YAC1D,MAAM,MAAM,GAAqC,IAAY,CAAC,MAAM,CAAA;YACpE,MAAM,KAAK,GAAY,IAAY,CAAC,KAAK,CAAA;YACzC,MAAM,IAAI,GAAY,IAAY,CAAC,IAAI,CAAA;YACvC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAA;YAEvE,MAAM,CAAC,KAAK,CAAC;iBACV,IAAI,CAAC,GAAG,EAAE;gBACT,QAAQ,EAAE,CAAA;gBACV,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAA;gBACpD,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;YAC/D,CAAC,CAAC;iBACD,KAAK,CAAC,CAAC,GAAQ,EAAE,EAAE;gBAClB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uDAAuD,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;gBACxG,QAAQ,EAAE,CAAA;gBACV,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;YAChE,CAAC,CAAC,CAAA;QACN,CAAC,EAAE,WAAW,CAAC,CAAA;IACjB,CAAC;IAEO,iBAAiB;QACvB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAA;QACjD,IAAI,CAAC,oBAAoB,EAAE;aACxB,IAAI,CAAC,GAAG,EAAE;YAET,IAAI,CAAC,8BAA8B,GAAG,WAAW,CAAC,GAAG,EAAE;gBACrD,IAAI,CAAC,sBAAsB,EAAE,CAAA;YAC/B,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,8BAA+B,CAAC,CAAA;QAClD,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,GAAQ,EAAE,EAAE;YAClB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;QACxE,CAAC,CAAC,CAAA;IACN,CAAC;IAEa,oBAAoB;;YAChC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAA;YAEpD,IAAI;gBACF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAQ,CAAC,yBAAyB,EAAE,CAAA;gBAC9D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,EAAE,MAAM,CAAC,CAAA;gBAC/D,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE;oBAC7D,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oGAAoG,IAAI,CAAC,OAAO,CAAC,SAAS,YAAY,CAAC,CAAA;oBACxJ,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAA;iBAChD;qBAAM;oBACL,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAA;iBAChC;aACF;YAAC,OAAO,GAAG,EAAE;gBACZ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4CAA4C,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;gBAC3E,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAA;gBACrD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAU,CAAA;aAEjD;QACH,CAAC;KAAA;IAEO,qBAAqB;QAC3B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAA;QACrD,IAAI,CAAC,2BAA2B,GAAG,WAAW,CAAC,GAAG,EAAE;YAClD,IAAI,CAAC,mBAAmB,EAAE,CAAA;QAC5B,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,sBAAuB,CAAC,CAAA;IAC1C,CAAC;IAEa,mBAAmB;;YAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;YACnD,IAAI,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAA;YAGnC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,CAAA;YAChE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC,CAAA;YAG5E,IAAI,IAAI,CAAC,iBAAiB,EAAE;gBAC1B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAA;gBAC7E,IAAI,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;gBAC5D,OAAM;aACP;YAGD,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAA;YAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,SAAU,CAAA;YAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAA;YAG7I,IAAI,qBAAqB,GAAG,KAAK,CAAA;YACjC,IAAI,2BAA2B,GAAG,KAAK,CAAA;YACvC,IAAI;gBACF,qBAAqB,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;gBAC3E,2BAA2B,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;aACxF;YAAC,OAAO,GAAG,EAAE;gBACZ,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qCAAqC,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;gBACpE,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAA;gBAC9B,IAAI,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC,CAAA;gBAC7D,OAAM;aACP;YAGD,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAE;gBAC7B,IAAI,qBAAqB,IAAI,2BAA2B,EAAE;oBACxD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAA;oBAChD,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;iBACtB;aACF;YAGD,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAA;YAC9B,IAAI,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9D,CAAC;KAAA;IAEa,gBAAgB,CAAC,WAAmB,EAAE,SAAiB;;YACnE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAA;YAEhD,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,OAAQ,CAAC,iBAAiB,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;YACrF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAA;YAEpD,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;YAEvD,MAAM,eAAe,GAAa,YAAG,CAAC,eAAe,EAAE,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YAClF,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,EAAE,eAAe,CAAC,MAAM,CAAC,CAAA;YAGxE,MAAM,aAAa,GAAG,mBAAU,CAAC,GAAG,EAAE,eAAe,CAAC,CAAA;YACtD,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;YACpE,IAAI,CAAC,IAAI,CAAC,sCAAsC,EAAE,EAAE,KAAK,EAAE,aAAa,CAAC,MAAM,EAAE,CAAC,CAAA;YAClF,aAAa,CAAC,OAAO,CAAC,CAAC,MAAc,EAAE,EAAE;gBACvC,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,4BAA6B,CAAC,CAAA;YAC/E,CAAC,CAAC,CAAA;YAGF,MAAM,eAAe,GAAG,eAAM,CAAC,eAAe,EAAE,CAAC,IAAS,EAAE,EAAE;gBAC5D,OAAO,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,oBAAoB,CAAA;YAClD,CAAC,CAAC,CAAA;YACF,MAAM,YAAY,GAAG,YAAG,CAAC,eAAe,EAAE,CAAC,IAAS,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;YACrE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE,eAAe,CAAC,MAAM,CAAC,CAAA;YACrE,IAAI,CAAC,IAAI,CAAC,qCAAqC,EAAE,EAAE,KAAK,EAAE,YAAY,CAAC,MAAM,EAAE,CAAC,CAAA;YAChF,YAAY,CAAC,OAAO,CAAC,CAAC,MAAc,EAAE,EAAE;gBAEtC,IAAI,CAAC,OAAQ,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAA;gBAC7C,IAAI,CAAC,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,2BAA4B,CAAC,CAAA;YAC9E,CAAC,CAAC,CAAA;YAEF,MAAM,WAAW,GAAG,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,CAAA;YAC3E,OAAO,WAAW,CAAA;QACpB,CAAC;KAAA;IAEa,sBAAsB,CAAC,WAAmB,EAAE,SAAiB;;YACzE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;YAGtD,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,OAAQ,CAAC,0BAA0B,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;YACnG,IAAI,CAAC,IAAI,CAAC,2CAA2C,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC,CAAA;YAClF,IAAI,WAAW,KAAK,CAAC,EAAE;gBACrB,OAAO,IAAI,CAAA;aACZ;YAED,MAAM,IAAI,CAAC,OAAQ,CAAC,0BAA0B,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;YAC/E,OAAO,KAAK,CAAA;QACd,CAAC;KAAA;IAEO,sBAAsB;QAC5B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAA;QAEtD,IAAI,IAAI,CAAC,kBAAkB,EAAE,EAAE;YAC7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,kEAAkE,IAAI,CAAC,OAAO,CAAC,SAAS,sDAAsD,CAAC,CAAA;YAChK,OAAM;SACP;QAED,OAAO,CAAC,IAAI,CAAC,kBAAkB,EAAE,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,EAAE;YACpE,IAAI,CAAC,yBAAyB,EAAE,CAAA;YAChC,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,iBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC,6BAA8B,CAAC,CAAA;SAChG;IACH,CAAC;IAEO,kBAAkB;QACxB,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IACvF,CAAC;IAEO,uBAAuB;QAC7B,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,IAAI,CAAC,OAAO,CAAC,mBAAoB,CAAA;IACtE,CAAC;IAEO,yBAAyB;QAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAA;QACzD,IAAI,CAAC,iBAAiB,IAAI,CAAC,CAAA;IAC7B,CAAC;IAKO,oBAAoB,CAAC,MAAc,EAAE,QAAgB;QAC3D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,yCAAyC,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAA;QAG3F,IAAI,MAAM,GAAG,IAAI,CAAC,iBAAiB,EAAE;YACnC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4DAA4D,EAAE,MAAM,CAAC,CAAA;YACvF,IAAI,CAAC,iBAAiB,GAAG,MAAM,CAAA;SAChC;QAED,IAAI,CAAC,UAAU,CAAC,IAAI,CAClB;YACE,MAAM,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;YACrC,KAAK,EAAE;gBACL,MAAM;aACP;YACD,IAAI,EAAE;gBACJ,UAAU,EAAE,eAAe;aAC5B;SACF,EACD,QAAQ,CACT,CAAA;IACH,CAAC;IAEa,aAAa,CAAC,KAAa;;YACvC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAA;YAE3D,MAAM,MAAM,GAAY,KAAa,CAAC,MAAM,CAAA;YAC5C,IAAI,aAAiC,CAAA;YACrC,IAAI,MAAM,GAAG,CAAC,EAAE;gBACd,aAAa,GAAG,MAAM,IAAI,CAAC,OAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;aACzD;YAED,MAAM,KAAK,GAAQ,MAAM,IAAI,CAAC,OAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YACvD,MAAM,SAAS,GAAG;gBAChB,MAAM;gBACN,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,cAAc,EAAE,0BAAW,CAAC,iBAAiB,CAAC,KAAK,EAAE,aAAa,CAAC;gBACnE,gBAAgB,EAAE,0BAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC;gBACxD,QAAQ,EAAE,IAAI,CAAC,oBAAoB;aACpC,CAAA;YAED,IAAI,IAAI,CAAC,OAAO,CAAC,sBAAsB,EAAE;gBACvC,IAAI,CAAC,0BAA0B,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,mCAAoC,CAAC,CAAA;aAC1F;YAED,MAAM,IAAI,CAAC,OAAQ,CAAC,YAAY,CAAC,SAAS,CAAC,CAAA;QAC7C,CAAC;KAAA;IAEO,0BAA0B,CAAC,KAAU,EAAE,QAAgB;QAC7D,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAA;QAE1D,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE;YACvB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,mCAAmC,CAAC,CAAA;YACrD,OAAM;SACP;QAED,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,WAAgB,EAAE,EAAE;YACpC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CACxB;gBACE,MAAM,EAAE,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,IAAI,CAAC;gBAC3C,KAAK,EAAE;oBACL,MAAM,EAAE,KAAK,CAAC,KAAK;oBACnB,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,WAAW;iBACZ;gBACD,IAAI,EAAE;oBACJ,UAAU,EAAE,qBAAqB;iBAClC;aACF,EACD,QAAQ,CACT,CAAA;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;IAEa,oCAAoC,CAAC,MAAc,EAAE,QAAgB;;YACjF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAA;YAEpE,MAAM,KAAK,GAAQ,MAAM,IAAI,CAAC,OAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YACvD,IAAI,CAAC,0BAA0B,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAA;QAClD,CAAC;KAAA;IAEa,mBAAmB,CAAC,KAAa;;YAC7C,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;YAEnD,MAAM,MAAM,GAAY,KAAa,CAAC,MAAM,CAAA;YAC5C,MAAM,IAAI,GAAY,KAAa,CAAC,IAAI,CAAA;YACxC,MAAM,EAAE,GAAS,KAAa,CAAC,WAAW,CAAA;YAC1C,MAAM,SAAS,GAAuB,gBAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;YACnF,MAAM,QAAQ,GAAuB,gBAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;YAChF,MAAM,eAAe,GAAG;gBACtB,MAAM;gBACN,IAAI;gBACJ,aAAa,EAAE,EAAE,CAAC,IAAI;gBACtB,IAAI,EAAE,EAAE,CAAC,IAAI;gBACb,IAAI,EAAE,EAAE,CAAC,IAAI;gBACb,UAAU,EAAE,EAAE,CAAC,OAAO;gBACtB,SAAS,EAAE,EAAE,CAAC,OAAO;gBACrB,SAAS;gBACT,QAAQ;gBACR,QAAQ,EAAE,IAAI,CAAC,0BAA0B;aAC1C,CAAA;YAED,MAAM,IAAI,CAAC,OAAQ,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAA;QACzD,CAAC;KAAA;IAEO,cAAc,CAAC,KAAa,EAAE,GAAW;QAC/C,MAAM,GAAG,GAAa,EAAE,CAAA;QACxB,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,EAAE,EAAE;YACjC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;SACZ;QACD,OAAO,GAAG,CAAA;IACZ,CAAC;CACF;AAhYD,sCAgYC"} -------------------------------------------------------------------------------- /dist/common/constants.d.ts: -------------------------------------------------------------------------------- 1 | declare const C: { 2 | network: { 3 | testnet: string; 4 | mainnet: string; 5 | }; 6 | storage: { 7 | memory: string; 8 | mongodb: string; 9 | }; 10 | rpc: { 11 | getblock: string; 12 | getblockcount: string; 13 | getversion: string; 14 | getrawtransaction: string; 15 | }; 16 | transaction: { 17 | MinerTransaction: string; 18 | ContractTransaction: string; 19 | InvocationTransaction: string; 20 | ClaimTransaction: string; 21 | }; 22 | }; 23 | export default C; 24 | -------------------------------------------------------------------------------- /dist/common/constants.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const C = { 4 | network: { 5 | testnet: 'testnet', 6 | mainnet: 'mainnet', 7 | }, 8 | storage: { 9 | memory: 'memory', 10 | mongodb: 'mongodb', 11 | }, 12 | rpc: { 13 | getblock: 'getblock', 14 | getblockcount: 'getblockcount', 15 | getversion: 'getversion', 16 | getrawtransaction: 'getrawtransaction', 17 | }, 18 | transaction: { 19 | MinerTransaction: 'MinerTransaction', 20 | ContractTransaction: 'ContractTransaction', 21 | InvocationTransaction: 'InvocationTransaction', 22 | ClaimTransaction: 'ClaimTransaction', 23 | }, 24 | }; 25 | exports.default = C; 26 | //# sourceMappingURL=constants.js.map -------------------------------------------------------------------------------- /dist/common/constants.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":";;AAAA,MAAM,CAAC,GAAG;IACR,OAAO,EAAE;QACP,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,SAAS;KACnB;IACD,OAAO,EAAE;QACP,MAAM,EAAE,QAAQ;QAChB,OAAO,EAAE,SAAS;KACnB;IACD,GAAG,EAAE;QACH,QAAQ,EAAE,UAAU;QACpB,aAAa,EAAE,eAAe;QAC9B,UAAU,EAAE,YAAY;QACxB,iBAAiB,EAAE,mBAAmB;KACvC;IACD,WAAW,EAAE;QACX,gBAAgB,EAAE,kBAAkB;QACpC,mBAAmB,EAAE,qBAAqB;QAC1C,qBAAqB,EAAE,uBAAuB;QAC9C,gBAAgB,EAAE,kBAAkB;KACrC;CACF,CAAA;AAED,kBAAe,CAAC,CAAA"} -------------------------------------------------------------------------------- /dist/common/profiles.d.ts: -------------------------------------------------------------------------------- 1 | declare const profiles: { 2 | rpc: { 3 | mainnet: { 4 | endpoint: string; 5 | }[]; 6 | testnet: { 7 | endpoint: string; 8 | }[]; 9 | }; 10 | assets: { 11 | id: string; 12 | name: string; 13 | symbol: string; 14 | type: string; 15 | precision: number; 16 | }[]; 17 | }; 18 | export default profiles; 19 | -------------------------------------------------------------------------------- /dist/common/profiles.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const profiles = { 4 | rpc: { 5 | mainnet: [ 6 | { endpoint: 'https://seed1.switcheo.network:10331' }, 7 | { endpoint: 'https://seed2.switcheo.network:10331' }, 8 | { endpoint: 'https://seed3.switcheo.network:10331' }, 9 | { endpoint: 'https://seed4.switcheo.network:10331' }, 10 | { endpoint: 'https://seed5.switcheo.network:10331' }, 11 | { endpoint: 'https://seed1.cityofzion.io:443' }, 12 | { endpoint: 'https://seed2.cityofzion.io:443' }, 13 | { endpoint: 'https://seed3.cityofzion.io:443' }, 14 | { endpoint: 'https://seed4.cityofzion.io:443' }, 15 | { endpoint: 'https://seed5.cityofzion.io:443' }, 16 | { endpoint: 'https://seed6.cityofzion.io:443' }, 17 | { endpoint: 'https://seed7.cityofzion.io:443' }, 18 | { endpoint: 'https://seed8.cityofzion.io:443' }, 19 | { endpoint: 'https://seed9.cityofzion.io:443' }, 20 | { endpoint: 'https://seed0.cityofzion.io:443' }, 21 | { endpoint: 'http://node1.ams2.bridgeprotocol.io' }, 22 | { endpoint: 'http://node2.ams2.bridgeprotocol.io' }, 23 | { endpoint: 'http://node1.nyc3.bridgeprotocol.io' }, 24 | { endpoint: 'http://node2.nyc3.bridgeprotocol.io' }, 25 | { endpoint: 'http://node1.sgp1.bridgeprotocol.io' }, 26 | { endpoint: 'http://node2.sgp1.bridgeprotocol.io' }, 27 | { endpoint: 'https://seed1.redpulse.com:443' }, 28 | { endpoint: 'https://seed2.redpulse.com:443' }, 29 | { endpoint: 'http://seed1.aphelion-neo.com:10332' }, 30 | { endpoint: 'http://seed2.aphelion-neo.com:10332' }, 31 | { endpoint: 'http://seed3.aphelion-neo.com:10332' }, 32 | { endpoint: 'http://seed4.aphelion-neo.com:10332' }, 33 | { endpoint: 'http://seed1.ngd.network:10332' }, 34 | { endpoint: 'http://seed2.ngd.network:10332' }, 35 | { endpoint: 'http://seed3.ngd.network:10332' }, 36 | { endpoint: 'http://seed4.ngd.network:10332' }, 37 | { endpoint: 'http://seed5.ngd.network:10332' }, 38 | { endpoint: 'http://seed6.ngd.network:10332' }, 39 | { endpoint: 'http://seed7.ngd.network:10332' }, 40 | { endpoint: 'http://seed8.ngd.network:10332' }, 41 | { endpoint: 'http://seed9.ngd.network:10332' }, 42 | { endpoint: 'http://seed10.ngd.network:10332' }, 43 | ], 44 | testnet: [ 45 | { endpoint: 'https://test1.cityofzion.io:443' }, 46 | { endpoint: 'https://test2.cityofzion.io:443' }, 47 | { endpoint: 'https://test3.cityofzion.io:443' }, 48 | { endpoint: 'https://test4.cityofzion.io:443' }, 49 | { endpoint: 'https://test5.cityofzion.io:443' }, 50 | ], 51 | }, 52 | assets: [ 53 | { id: '0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b', name: 'NEO', symbol: 'NEO', type: 'GoverningToken', precision: 0 }, 54 | { id: '0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7', name: 'GAS', symbol: 'GAS', type: 'UtilityToken', precision: 8 }, 55 | ], 56 | }; 57 | exports.default = profiles; 58 | //# sourceMappingURL=profiles.js.map -------------------------------------------------------------------------------- /dist/common/profiles.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"profiles.js","sourceRoot":"","sources":["../../src/common/profiles.ts"],"names":[],"mappings":";;AAAA,MAAM,QAAQ,GAAG;IACf,GAAG,EAAE;QACH,OAAO,EAAE;YACP,EAAE,QAAQ,EAAE,sCAAsC,EAAE;YACpD,EAAE,QAAQ,EAAE,sCAAsC,EAAE;YACpD,EAAE,QAAQ,EAAE,sCAAsC,EAAE;YACpD,EAAE,QAAQ,EAAE,sCAAsC,EAAE;YACpD,EAAE,QAAQ,EAAE,sCAAsC,EAAE;YACpD,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,qCAAqC,EAAE;YACnD,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,gCAAgC,EAAE;YAC9C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;SAChD;QACD,OAAO,EAAE;YACP,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;YAC/C,EAAE,QAAQ,EAAE,iCAAiC,EAAE;SAChD;KACF;IACD,MAAM,EAAE;QACN,EAAE,EAAE,EAAE,oEAAoE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,gBAAgB,EAAE,SAAS,EAAE,CAAC,EAAE;QAC9I,EAAE,EAAE,EAAE,oEAAoE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,SAAS,EAAE,CAAC,EAAE;KAC7I;CACF,CAAA;AAED,kBAAe,QAAQ,CAAA"} -------------------------------------------------------------------------------- /dist/core/api.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { EventEmitter } from 'events'; 3 | import { LoggerOptions } from 'node-log-it'; 4 | import { Mesh } from './mesh'; 5 | import { MemoryStorage } from '../storages/memory-storage'; 6 | import { MongodbStorage } from '../storages/mongodb-storage'; 7 | export interface ApiOptions { 8 | insertToStorage?: boolean; 9 | checkReadyIntervalMs?: number; 10 | loggerOptions?: LoggerOptions; 11 | } 12 | export declare class Api extends EventEmitter { 13 | private mesh; 14 | private storage?; 15 | private options; 16 | private logger; 17 | private checkReadyIntervalId?; 18 | constructor(mesh: Mesh, storage?: MemoryStorage | MongodbStorage, options?: ApiOptions); 19 | getBlockCount(): Promise; 20 | getBlock(height: number): Promise; 21 | getTransaction(transactionId: string): Promise; 22 | close(): void; 23 | private storageInsertHandler; 24 | private validateOptionalParameters; 25 | private checkMeshAndStorageReady; 26 | private storeBlockCount; 27 | private storeBlock; 28 | private getBlockCountFromMesh; 29 | private getBlockFromMesh; 30 | private getBlockAndNodeMetaFromMesh; 31 | private getTransactionFromMesh; 32 | } 33 | -------------------------------------------------------------------------------- /dist/core/api.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __importDefault = (this && this.__importDefault) || function (mod) { 11 | return (mod && mod.__esModule) ? mod : { "default": mod }; 12 | }; 13 | Object.defineProperty(exports, "__esModule", { value: true }); 14 | const events_1 = require("events"); 15 | const node_log_it_1 = require("node-log-it"); 16 | const lodash_1 = require("lodash"); 17 | const constants_1 = __importDefault(require("../common/constants")); 18 | const neo_validator_1 = require("../validators/neo-validator"); 19 | const MODULE_NAME = 'Api'; 20 | const DEFAULT_OPTIONS = { 21 | insertToStorage: true, 22 | checkReadyIntervalMs: 200, 23 | loggerOptions: {}, 24 | }; 25 | class Api extends events_1.EventEmitter { 26 | constructor(mesh, storage, options = {}) { 27 | super(); 28 | this.mesh = mesh; 29 | this.storage = storage; 30 | this.options = lodash_1.merge({}, DEFAULT_OPTIONS, options); 31 | this.validateOptionalParameters(); 32 | this.logger = new node_log_it_1.Logger(MODULE_NAME, this.options.loggerOptions); 33 | this.checkMeshAndStorageReady(); 34 | this.on('storage:insert', this.storageInsertHandler.bind(this)); 35 | this.logger.debug('constructor completes.'); 36 | } 37 | getBlockCount() { 38 | return __awaiter(this, void 0, void 0, function* () { 39 | this.logger.debug('getBlockCount triggered.'); 40 | if (!this.storage) { 41 | this.logger.debug('No storage delegate detected.'); 42 | return this.getBlockCountFromMesh(); 43 | } 44 | let blockHeight; 45 | try { 46 | blockHeight = yield this.storage.getHighestBlockHeight(); 47 | return blockHeight; 48 | } 49 | catch (err) { 50 | } 51 | this.logger.debug('Cannot find result from storage delegate, attempt to fetch from mesh instead...'); 52 | blockHeight = yield this.getBlockCountFromMesh(); 53 | this.logger.debug('Successfully fetch result from mesh.'); 54 | this.emit('storage:insert', { method: constants_1.default.rpc.getblockcount, result: blockHeight }); 55 | return blockHeight; 56 | }); 57 | } 58 | getBlock(height) { 59 | return __awaiter(this, void 0, void 0, function* () { 60 | this.logger.debug('getBlock triggered. height:', height); 61 | neo_validator_1.NeoValidator.validateHeight(height); 62 | if (!this.storage) { 63 | this.logger.debug('No storage delegate detected.'); 64 | return this.getBlockFromMesh(height); 65 | } 66 | let block; 67 | try { 68 | block = yield this.storage.getBlock(height); 69 | return block; 70 | } 71 | catch (err) { 72 | this.logger.debug('Cannot find result from storage delegate. Error:', err.message); 73 | } 74 | this.logger.debug('Attempt to fetch from mesh instead...'); 75 | const blockResponse = yield this.getBlockAndNodeMetaFromMesh(height); 76 | this.logger.debug('Successfully fetch result from mesh.'); 77 | block = blockResponse.block; 78 | const nodeMeta = blockResponse.nodeMeta; 79 | this.emit('storage:insert', { method: constants_1.default.rpc.getblock, result: { height, block }, nodeMeta }); 80 | return block; 81 | }); 82 | } 83 | getTransaction(transactionId) { 84 | return __awaiter(this, void 0, void 0, function* () { 85 | this.logger.debug('getBlock triggered. transactionId:', transactionId); 86 | neo_validator_1.NeoValidator.validateTransactionId(transactionId); 87 | if (!this.storage) { 88 | this.logger.debug('No storage delegate detected.'); 89 | return this.getTransactionFromMesh(transactionId); 90 | } 91 | let transaction; 92 | try { 93 | transaction = yield this.storage.getTransaction(transactionId); 94 | return transaction; 95 | } 96 | catch (err) { 97 | this.logger.debug('Cannot find result from storage delegate. Error:', err.message); 98 | } 99 | this.logger.debug('Attempt to fetch from mesh instead...'); 100 | transaction = yield this.getTransactionFromMesh(transactionId); 101 | return transaction; 102 | }); 103 | } 104 | close() { 105 | clearInterval(this.checkReadyIntervalId); 106 | } 107 | storageInsertHandler(payload) { 108 | if (!this.options.insertToStorage) { 109 | return; 110 | } 111 | this.logger.debug('storageInsertHandler triggered.'); 112 | if (payload.method === constants_1.default.rpc.getblockcount) { 113 | this.storeBlockCount(payload); 114 | } 115 | else if (payload.method === constants_1.default.rpc.getblock) { 116 | this.storeBlock(payload); 117 | } 118 | else { 119 | throw new Error('Not implemented.'); 120 | } 121 | } 122 | validateOptionalParameters() { 123 | } 124 | checkMeshAndStorageReady() { 125 | this.logger.debug('checkMeshAndStorageReady triggered.'); 126 | this.checkReadyIntervalId = setInterval(() => { 127 | const meshReady = this.mesh.isReady(); 128 | const storageReady = this.storage ? this.storage.isReady() : true; 129 | if (meshReady && storageReady) { 130 | this.emit('ready'); 131 | clearInterval(this.checkReadyIntervalId); 132 | } 133 | }, this.options.checkReadyIntervalMs); 134 | } 135 | storeBlockCount(payload) { 136 | if (this.storage) { 137 | const blockHeight = payload.result; 138 | this.storage.setBlockCount(blockHeight); 139 | } 140 | } 141 | storeBlock(payload) { 142 | if (this.storage) { 143 | const height = payload.result.height; 144 | const block = payload.result.block; 145 | const source = payload.nodeMeta ? payload.nodeMeta.endpoint : 'api:storeBlock'; 146 | this.storage.setBlock(height, block, { source }); 147 | } 148 | } 149 | getBlockCountFromMesh() { 150 | return __awaiter(this, void 0, void 0, function* () { 151 | this.logger.debug('getBlockCountFromMesh triggered.'); 152 | const highestNode = this.mesh.getHighestNode(); 153 | if (highestNode && highestNode.blockHeight) { 154 | return highestNode.blockHeight; 155 | } 156 | else { 157 | throw new Error('Edge case not implemented.'); 158 | } 159 | }); 160 | } 161 | getBlockFromMesh(height) { 162 | return __awaiter(this, void 0, void 0, function* () { 163 | this.logger.debug('getBlockFromMesh triggered.'); 164 | const blockResponse = yield this.getBlockAndNodeMetaFromMesh(height); 165 | return blockResponse.block; 166 | }); 167 | } 168 | getBlockAndNodeMetaFromMesh(height) { 169 | return __awaiter(this, void 0, void 0, function* () { 170 | this.logger.debug('getBlockAndNodeMetaFromMesh triggered.'); 171 | const highestNode = this.mesh.getHighestNode(); 172 | if (highestNode && highestNode.blockHeight) { 173 | const nodeMeta = highestNode.getNodeMeta(); 174 | const block = yield highestNode.getBlock(height); 175 | return { block, nodeMeta }; 176 | } 177 | else { 178 | throw new Error('Edge case not implemented.'); 179 | } 180 | }); 181 | } 182 | getTransactionFromMesh(transactionId) { 183 | return __awaiter(this, void 0, void 0, function* () { 184 | this.logger.debug('getTransactionFromMesh triggered.'); 185 | const highestNode = this.mesh.getHighestNode(); 186 | if (highestNode && highestNode.blockHeight) { 187 | const transaction = yield highestNode.getTransaction(transactionId); 188 | return transaction; 189 | } 190 | else { 191 | throw new Error('Edge case not implemented.'); 192 | } 193 | }); 194 | } 195 | } 196 | exports.Api = Api; 197 | //# sourceMappingURL=api.js.map -------------------------------------------------------------------------------- /dist/core/api.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/core/api.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/core/mesh.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { EventEmitter } from 'events'; 3 | import { LoggerOptions } from 'node-log-it'; 4 | import { Node } from './node'; 5 | export interface MeshOptions { 6 | startBenchmarkOnInit?: boolean; 7 | toFetchUserAgent?: boolean; 8 | benchmarkIntervalMs?: number; 9 | fetchMissingUserAgentIntervalMs?: number; 10 | refreshUserAgentIntervalMs?: number; 11 | minActiveNodesRequired?: number; 12 | pendingRequestsThreshold?: number; 13 | loggerOptions?: LoggerOptions; 14 | } 15 | export declare class Mesh extends EventEmitter { 16 | nodes: Node[]; 17 | private _isReady; 18 | private benchmarkIntervalId?; 19 | private fetchMissingUserAgentIntervalId?; 20 | private refreshUserAgentIntervalId?; 21 | private options; 22 | private logger; 23 | constructor(nodes: Node[], options?: MeshOptions); 24 | isReady(): boolean; 25 | startBenchmark(): void; 26 | stopBenchmark(): void; 27 | close(): void; 28 | getFastestNode(activeOnly?: boolean): Node | undefined; 29 | getHighestNode(activeOnly?: boolean): Node | undefined; 30 | getRandomNode(activeOnly?: boolean): Node | undefined; 31 | getOptimalNode(height: number, activeOnly?: boolean): Node | undefined; 32 | private validateOptionalParameters; 33 | private performBenchmark; 34 | private getNodeToBenchmark; 35 | private performFetchMissingUserAgent; 36 | private performRefreshUserAgent; 37 | private checkMeshReady; 38 | private setReady; 39 | private listActiveNodes; 40 | } 41 | -------------------------------------------------------------------------------- /dist/core/mesh.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const events_1 = require("events"); 4 | const node_log_it_1 = require("node-log-it"); 5 | const lodash_1 = require("lodash"); 6 | const MODULE_NAME = 'Mesh'; 7 | const DEFAULT_OPTIONS = { 8 | startBenchmarkOnInit: true, 9 | toFetchUserAgent: true, 10 | benchmarkIntervalMs: 2000, 11 | fetchMissingUserAgentIntervalMs: 5000, 12 | refreshUserAgentIntervalMs: 5 * 60 * 1000, 13 | minActiveNodesRequired: 2, 14 | pendingRequestsThreshold: 5, 15 | loggerOptions: {}, 16 | }; 17 | class Mesh extends events_1.EventEmitter { 18 | constructor(nodes, options = {}) { 19 | super(); 20 | this._isReady = false; 21 | this.nodes = nodes; 22 | if (this.nodes.length === 0) { 23 | throw new Error('Mesh must have 1 or more nodes.'); 24 | } 25 | this.options = lodash_1.merge({}, DEFAULT_OPTIONS, options); 26 | this.validateOptionalParameters(); 27 | this.logger = new node_log_it_1.Logger(MODULE_NAME, this.options.loggerOptions); 28 | if (this.options.startBenchmarkOnInit) { 29 | this.startBenchmark(); 30 | } 31 | this.logger.debug('constructor completes.'); 32 | } 33 | isReady() { 34 | return this._isReady; 35 | } 36 | startBenchmark() { 37 | this.logger.debug('startBenchmark triggered.'); 38 | const unknownNodes = lodash_1.filter(this.nodes, (n) => n.isActive === undefined); 39 | this.logger.debug('unknownNodes.length:', unknownNodes.length); 40 | unknownNodes.forEach((n) => { 41 | n.getBlockCount() 42 | .then(() => { 43 | this.checkMeshReady(); 44 | }) 45 | .catch((err) => { 46 | this.logger.info('node.getBlockCount() failed, but to continue. Endpoint:', n.endpoint, 'Message:', err.message); 47 | }); 48 | }); 49 | if (this.options.toFetchUserAgent) { 50 | unknownNodes.forEach((n) => { 51 | n.getVersion().catch((err) => { 52 | this.logger.info('node.getVersion() failed, but to continue. Endpoint:', n.endpoint, 'Message:', err.message); 53 | }); 54 | }); 55 | this.fetchMissingUserAgentIntervalId = setInterval(() => this.performFetchMissingUserAgent(), this.options.fetchMissingUserAgentIntervalMs); 56 | this.refreshUserAgentIntervalId = setInterval(() => this.performRefreshUserAgent(), this.options.refreshUserAgentIntervalMs); 57 | } 58 | this.benchmarkIntervalId = setInterval(() => this.performBenchmark(), this.options.benchmarkIntervalMs); 59 | } 60 | stopBenchmark() { 61 | this.logger.debug('stopBenchmark triggered.'); 62 | if (this.benchmarkIntervalId) { 63 | clearInterval(this.benchmarkIntervalId); 64 | } 65 | if (this.fetchMissingUserAgentIntervalId) { 66 | clearInterval(this.fetchMissingUserAgentIntervalId); 67 | } 68 | if (this.refreshUserAgentIntervalId) { 69 | clearInterval(this.refreshUserAgentIntervalId); 70 | } 71 | } 72 | close() { 73 | this.logger.debug('close triggered.'); 74 | this.stopBenchmark(); 75 | this.nodes.forEach((n) => { 76 | n.close(); 77 | }); 78 | } 79 | getFastestNode(activeOnly = true) { 80 | this.logger.debug('getFastestNode triggered.'); 81 | let nodePool = activeOnly ? this.listActiveNodes() : this.nodes; 82 | if (nodePool.length === 0) { 83 | return undefined; 84 | } 85 | nodePool = lodash_1.filter(nodePool, (n) => n.latency !== undefined); 86 | if (nodePool.length === 0) { 87 | return undefined; 88 | } 89 | return lodash_1.minBy(nodePool, 'latency'); 90 | } 91 | getHighestNode(activeOnly = true) { 92 | this.logger.debug('getHighestNode triggered.'); 93 | let nodePool = activeOnly ? this.listActiveNodes() : this.nodes; 94 | if (nodePool.length === 0) { 95 | return undefined; 96 | } 97 | nodePool = lodash_1.filter(nodePool, (n) => n.blockHeight !== undefined); 98 | if (nodePool.length === 0) { 99 | return undefined; 100 | } 101 | return lodash_1.maxBy(nodePool, 'blockHeight'); 102 | } 103 | getRandomNode(activeOnly = true) { 104 | this.logger.debug('getRandomNode triggered.'); 105 | const nodePool = activeOnly ? this.listActiveNodes() : this.nodes; 106 | if (nodePool.length === 0) { 107 | return undefined; 108 | } 109 | const randomIndex = lodash_1.random(0, nodePool.length - 1); 110 | return nodePool[randomIndex]; 111 | } 112 | getOptimalNode(height, activeOnly = true) { 113 | this.logger.debug('getOptimalNode triggered.'); 114 | const nodePool = activeOnly ? this.listActiveNodes() : this.nodes; 115 | if (nodePool.length === 0) { 116 | return undefined; 117 | } 118 | const qualifyHeightNodes = lodash_1.filter(this.nodes, (n) => n.blockHeight !== undefined && n.blockHeight >= height); 119 | if (qualifyHeightNodes.length === 0) { 120 | return undefined; 121 | } 122 | const qualifyPendingNodes = lodash_1.filter(qualifyHeightNodes, (n) => !n.pendingRequests || n.pendingRequests <= this.options.pendingRequestsThreshold); 123 | if (qualifyPendingNodes.length === 0) { 124 | const randomIndex = lodash_1.random(0, qualifyHeightNodes.length - 1); 125 | return qualifyHeightNodes[randomIndex]; 126 | } 127 | return lodash_1.minBy(qualifyPendingNodes, 'latency'); 128 | } 129 | validateOptionalParameters() { 130 | } 131 | performBenchmark() { 132 | this.logger.debug('performBenchmark triggered.'); 133 | const node = this.getNodeToBenchmark(); 134 | if (node) { 135 | node.getBlockCount().catch((err) => { 136 | this.logger.info('node.getBlockCount error in performBenchmark(). Endpoint:', node.endpoint, 'Message:', err.message); 137 | }); 138 | } 139 | else { 140 | this.logger.info('Unable to find a suitable node to perform benchmark.'); 141 | } 142 | } 143 | getNodeToBenchmark() { 144 | this.logger.debug('getNodeToBenchmark triggered.'); 145 | const nodePool = lodash_1.filter(this.nodes, (n) => !n.isBenchmarking); 146 | if (nodePool.length === 0) { 147 | return undefined; 148 | } 149 | const unknownNode = lodash_1.find(nodePool, (n) => n.lastPingTimestamp === undefined); 150 | if (unknownNode) { 151 | return unknownNode; 152 | } 153 | const targetNode = lodash_1.minBy(nodePool, (n) => n.lastPingTimestamp); 154 | return targetNode; 155 | } 156 | performFetchMissingUserAgent() { 157 | this.logger.debug('performBenchmark triggered.'); 158 | const nodePool = lodash_1.filter(this.nodes, (n) => n.userAgent === undefined); 159 | nodePool.forEach((n) => { 160 | n.getVersion().catch((err) => { 161 | this.logger.info('node.getVersion() failed, but to continue. Endpoint:', n.endpoint, 'Message:', err.message); 162 | }); 163 | }); 164 | } 165 | performRefreshUserAgent() { 166 | this.logger.debug('performRefreshUserAgent triggered.'); 167 | this.nodes.forEach((n) => { 168 | n.getVersion().catch((err) => { 169 | this.logger.info('node.getVersion() failed, but to continue. Endpoint:', n.endpoint, 'Message:', err.message); 170 | }); 171 | }); 172 | } 173 | checkMeshReady() { 174 | this.logger.debug('checkMeshReady triggered.'); 175 | const activeNodes = this.listActiveNodes(); 176 | if (!this.options.minActiveNodesRequired || activeNodes.length >= this.options.minActiveNodesRequired) { 177 | if (!this._isReady) { 178 | this.setReady(); 179 | this.logger.debug('mesh is considered to be now ready.'); 180 | } 181 | } 182 | } 183 | setReady() { 184 | this._isReady = true; 185 | this.emit('ready'); 186 | } 187 | listActiveNodes() { 188 | return lodash_1.filter(this.nodes, { isActive: true }); 189 | } 190 | } 191 | exports.Mesh = Mesh; 192 | //# sourceMappingURL=mesh.js.map -------------------------------------------------------------------------------- /dist/core/mesh.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"mesh.js","sourceRoot":"","sources":["../../src/core/mesh.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/core/node.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { EventEmitter } from 'events'; 3 | import { LoggerOptions } from 'node-log-it'; 4 | export interface NodeMeta { 5 | isActive: boolean | undefined; 6 | pendingRequests: number | undefined; 7 | latency: number | undefined; 8 | blockHeight: number | undefined; 9 | lastSeenTimestamp: number | undefined; 10 | userAgent: string | undefined; 11 | endpoint: string; 12 | } 13 | export interface NodeOptions { 14 | toLogReliability?: boolean; 15 | truncateRequestLogIntervalMs?: number; 16 | requestLogTtl?: number; 17 | timeout?: number; 18 | loggerOptions?: LoggerOptions; 19 | } 20 | export declare class Node extends EventEmitter { 21 | isActive: boolean | undefined; 22 | pendingRequests: number | undefined; 23 | latency: number | undefined; 24 | blockHeight: number | undefined; 25 | lastPingTimestamp: number | undefined; 26 | lastSeenTimestamp: number | undefined; 27 | userAgent: string | undefined; 28 | endpoint: string; 29 | isBenchmarking: boolean; 30 | private options; 31 | private logger; 32 | private requestLogs; 33 | private truncateRequestLogIntervalId?; 34 | constructor(endpoint: string, options?: NodeOptions); 35 | getBlock(height: number, isVerbose?: boolean): Promise; 36 | getBlockCount(): Promise; 37 | getVersion(): Promise; 38 | getTransaction(transactionId: string, isVerbose?: boolean): Promise; 39 | getNodeMeta(): NodeMeta; 40 | getNodeReliability(): number | undefined; 41 | getShapedLatency(): number | undefined; 42 | close(): void; 43 | private queryInitHandler; 44 | private queryCompleteHandler; 45 | private validateOptionalParameters; 46 | private startBenchmark; 47 | private stopBenchmark; 48 | private truncateRequestLog; 49 | private query; 50 | private increasePendingRequest; 51 | private decreasePendingRequest; 52 | private getRequestConfig; 53 | } 54 | -------------------------------------------------------------------------------- /dist/core/node.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | var __importDefault = (this && this.__importDefault) || function (mod) { 11 | return (mod && mod.__esModule) ? mod : { "default": mod }; 12 | }; 13 | Object.defineProperty(exports, "__esModule", { value: true }); 14 | const events_1 = require("events"); 15 | const node_log_it_1 = require("node-log-it"); 16 | const lodash_1 = require("lodash"); 17 | const rpc_delegate_1 = require("../delegates/rpc-delegate"); 18 | const constants_1 = __importDefault(require("../common/constants")); 19 | const neo_validator_1 = require("../validators/neo-validator"); 20 | const MODULE_NAME = 'Node'; 21 | const DEFAULT_ID = 0; 22 | const DEFAULT_OPTIONS = { 23 | toLogReliability: false, 24 | truncateRequestLogIntervalMs: 30 * 1000, 25 | requestLogTtl: 5 * 60 * 1000, 26 | timeout: 30000, 27 | loggerOptions: {}, 28 | }; 29 | class Node extends events_1.EventEmitter { 30 | constructor(endpoint, options = {}) { 31 | super(); 32 | this.isBenchmarking = false; 33 | this.requestLogs = []; 34 | this.endpoint = endpoint; 35 | this.options = lodash_1.merge({}, DEFAULT_OPTIONS, options); 36 | this.validateOptionalParameters(); 37 | this.logger = new node_log_it_1.Logger(MODULE_NAME, this.options.loggerOptions); 38 | if (this.options.toLogReliability) { 39 | this.truncateRequestLogIntervalId = setInterval(() => this.truncateRequestLog(), this.options.truncateRequestLogIntervalMs); 40 | } 41 | this.on('query:init', this.queryInitHandler.bind(this)); 42 | this.on('query:complete', this.queryCompleteHandler.bind(this)); 43 | this.logger.debug('constructor completes.'); 44 | } 45 | getBlock(height, isVerbose = true) { 46 | return __awaiter(this, void 0, void 0, function* () { 47 | this.logger.debug('getBlock triggered.'); 48 | neo_validator_1.NeoValidator.validateHeight(height); 49 | const verboseKey = isVerbose ? 1 : 0; 50 | return yield this.query(constants_1.default.rpc.getblock, [height, verboseKey]); 51 | }); 52 | } 53 | getBlockCount() { 54 | return __awaiter(this, void 0, void 0, function* () { 55 | this.logger.debug('getBlockCount triggered.'); 56 | return yield this.query(constants_1.default.rpc.getblockcount); 57 | }); 58 | } 59 | getVersion() { 60 | return __awaiter(this, void 0, void 0, function* () { 61 | this.logger.debug('getVersion triggered.'); 62 | return yield this.query(constants_1.default.rpc.getversion); 63 | }); 64 | } 65 | getTransaction(transactionId, isVerbose = true) { 66 | return __awaiter(this, void 0, void 0, function* () { 67 | this.logger.debug('transactionId triggered.'); 68 | const verboseKey = isVerbose ? 1 : 0; 69 | return yield this.query(constants_1.default.rpc.getrawtransaction, [transactionId, verboseKey]); 70 | }); 71 | } 72 | getNodeMeta() { 73 | return { 74 | isActive: this.isActive, 75 | pendingRequests: this.pendingRequests, 76 | latency: this.latency, 77 | blockHeight: this.blockHeight, 78 | lastSeenTimestamp: this.lastSeenTimestamp, 79 | userAgent: this.userAgent, 80 | endpoint: this.endpoint, 81 | }; 82 | } 83 | getNodeReliability() { 84 | const requestCount = this.requestLogs.length; 85 | if (requestCount === 0) { 86 | return undefined; 87 | } 88 | const successCount = lodash_1.filter(this.requestLogs, (logObj) => logObj.isSuccess === true).length; 89 | return successCount / requestCount; 90 | } 91 | getShapedLatency() { 92 | this.logger.debug('getShapedLatency triggered.'); 93 | if (this.requestLogs.length === 0) { 94 | return undefined; 95 | } 96 | const logPool = lodash_1.filter(this.requestLogs, (logObj) => logObj.isSuccess === true && logObj.latency !== undefined); 97 | if (logPool.length === 0) { 98 | return undefined; 99 | } 100 | const averageLatency = lodash_1.round(lodash_1.meanBy(logPool, (logObj) => logObj.latency), 0); 101 | return averageLatency; 102 | } 103 | close() { 104 | this.logger.debug('close triggered.'); 105 | if (this.truncateRequestLogIntervalId) { 106 | clearInterval(this.truncateRequestLogIntervalId); 107 | } 108 | } 109 | queryInitHandler(payload) { 110 | this.logger.debug('queryInitHandler triggered.'); 111 | this.startBenchmark(payload); 112 | } 113 | queryCompleteHandler(payload) { 114 | this.logger.debug('queryCompleteHandler triggered.'); 115 | this.stopBenchmark(payload); 116 | } 117 | validateOptionalParameters() { 118 | } 119 | startBenchmark(payload) { 120 | this.logger.debug('startBenchmark triggered.'); 121 | this.increasePendingRequest(); 122 | if (payload.method === constants_1.default.rpc.getblockcount) { 123 | if (this.isBenchmarking) { 124 | this.logger.debug('An benchmarking schedule is already in place. Skipping... endpoint:', this.endpoint); 125 | } 126 | else { 127 | this.isBenchmarking = true; 128 | } 129 | } 130 | } 131 | stopBenchmark(payload) { 132 | this.logger.debug('stopBenchmark triggered.'); 133 | this.decreasePendingRequest(); 134 | this.lastPingTimestamp = Date.now(); 135 | if (!payload.isSuccess) { 136 | this.isActive = false; 137 | } 138 | else { 139 | this.isActive = true; 140 | this.lastSeenTimestamp = Date.now(); 141 | } 142 | if (payload.blockHeight) { 143 | this.blockHeight = payload.blockHeight; 144 | } 145 | if (payload.userAgent) { 146 | this.userAgent = payload.userAgent; 147 | } 148 | if (payload.method === constants_1.default.rpc.getblockcount) { 149 | if (!this.isBenchmarking) { 150 | this.logger.debug('There are no running benchmarking schedule in place. Skipping... endpoint:', this.endpoint); 151 | } 152 | else { 153 | this.isBenchmarking = false; 154 | if (payload.latency) { 155 | this.latency = payload.latency; 156 | } 157 | if (this.options.toLogReliability) { 158 | if (!payload.isSuccess) { 159 | this.requestLogs.push({ 160 | timestamp: Date.now(), 161 | isSuccess: payload.isSuccess, 162 | }); 163 | } 164 | else { 165 | this.requestLogs.push({ 166 | timestamp: Date.now(), 167 | isSuccess: payload.isSuccess, 168 | latency: this.latency, 169 | }); 170 | } 171 | } 172 | } 173 | } 174 | } 175 | truncateRequestLog() { 176 | this.logger.debug('truncateRequestLog triggered.'); 177 | const cutOffTimestamp = Date.now() - this.options.requestLogTtl; 178 | this.requestLogs = lodash_1.remove(this.requestLogs, (logObj) => logObj.timestamp > cutOffTimestamp); 179 | } 180 | query(method, params = [], id = DEFAULT_ID) { 181 | return __awaiter(this, void 0, void 0, function* () { 182 | this.logger.debug('query triggered. method:', method); 183 | this.emit('query:init', { method, params, id }); 184 | const requestConfig = this.getRequestConfig(); 185 | const t0 = Date.now(); 186 | try { 187 | const res = yield rpc_delegate_1.RpcDelegate.query(this.endpoint, method, params, id, requestConfig); 188 | const latency = Date.now() - t0; 189 | const result = res.result; 190 | const blockHeight = method === constants_1.default.rpc.getblockcount ? result : undefined; 191 | const userAgent = method === constants_1.default.rpc.getversion ? result.useragent : undefined; 192 | this.emit('query:complete', { isSuccess: true, method, latency, blockHeight, userAgent }); 193 | return result; 194 | } 195 | catch (err) { 196 | this.emit('query:complete', { isSuccess: false, method, error: err }); 197 | throw err; 198 | } 199 | }); 200 | } 201 | increasePendingRequest() { 202 | this.logger.debug('increasePendingRequest triggered.'); 203 | if (this.pendingRequests) { 204 | this.pendingRequests += 1; 205 | } 206 | else { 207 | this.pendingRequests = 1; 208 | } 209 | } 210 | decreasePendingRequest() { 211 | this.logger.debug('decreasePendingRequest triggered.'); 212 | if (this.pendingRequests) { 213 | this.pendingRequests -= 1; 214 | } 215 | else { 216 | this.pendingRequests = 0; 217 | } 218 | } 219 | getRequestConfig() { 220 | const config = {}; 221 | if (this.options.timeout) { 222 | config.timeout = this.options.timeout; 223 | } 224 | return config; 225 | } 226 | } 227 | exports.Node = Node; 228 | //# sourceMappingURL=node.js.map -------------------------------------------------------------------------------- /dist/core/node.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/core/node.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/core/syncer.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { EventEmitter } from 'events'; 3 | import { LoggerOptions } from 'node-log-it'; 4 | import { Mesh } from './mesh'; 5 | import { MemoryStorage } from '../storages/memory-storage'; 6 | import { MongodbStorage } from '../storages/mongodb-storage'; 7 | export interface SyncerOptions { 8 | minHeight?: number; 9 | maxHeight?: number; 10 | blockRedundancy?: number; 11 | checkRedundancyBeforeStoreBlock?: boolean; 12 | startOnInit?: boolean; 13 | toSyncIncremental?: boolean; 14 | toSyncForMissingBlocks?: boolean; 15 | toPruneRedundantBlocks?: boolean; 16 | storeQueueConcurrency?: number; 17 | pruneQueueConcurrency?: number; 18 | enqueueBlockIntervalMs?: number; 19 | verifyBlocksIntervalMs?: number; 20 | maxStoreQueueLength?: number; 21 | retryEnqueueDelayMs?: number; 22 | standardEnqueueBlockPriority?: number; 23 | retryEnqueueBlockPriority?: number; 24 | missingEnqueueStoreBlockPriority?: number; 25 | enqueuePruneBlockPriority?: number; 26 | maxPruneChunkSize?: number; 27 | loggerOptions?: LoggerOptions; 28 | } 29 | export declare class Syncer extends EventEmitter { 30 | private _isRunning; 31 | private storeQueue; 32 | private pruneQueue; 33 | private blockWritePointer; 34 | private mesh; 35 | private storage?; 36 | private options; 37 | private logger; 38 | private enqueueStoreBlockIntervalId?; 39 | private blockVerificationIntervalId?; 40 | private isVerifyingBlocks; 41 | constructor(mesh: Mesh, storage?: MemoryStorage | MongodbStorage, options?: SyncerOptions); 42 | isRunning(): boolean; 43 | start(): void; 44 | stop(): void; 45 | close(): void; 46 | private storeBlockCompleteHandler; 47 | private validateOptionalParameters; 48 | private getPriorityQueue; 49 | private initStoreBlock; 50 | private doEnqueueStoreBlock; 51 | private isReachedMaxHeight; 52 | private isReachedHighestBlock; 53 | private isReachedMaxStoreQueueLength; 54 | private setBlockWritePointer; 55 | private initBlockVerification; 56 | private doBlockVerification; 57 | private increaseBlockWritePointer; 58 | private enqueueStoreBlock; 59 | private enqueuePruneBlock; 60 | private storeBlock; 61 | private pruneBlock; 62 | } 63 | -------------------------------------------------------------------------------- /dist/delegates/rpc-delegate.d.ts: -------------------------------------------------------------------------------- 1 | import { AxiosRequestConfig } from 'axios'; 2 | export declare class RpcDelegate { 3 | static query(url: string, method: string, params: any[], id: number, requestConfig: AxiosRequestConfig): Promise; 4 | } 5 | -------------------------------------------------------------------------------- /dist/delegates/rpc-delegate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | Object.defineProperty(exports, "__esModule", { value: true }); 11 | const neon_js_1 = require("@cityofzion/neon-js"); 12 | const rpc_validator_1 = require("../validators/rpc-validator"); 13 | class RpcDelegate { 14 | static query(url, method, params, id, requestConfig) { 15 | return __awaiter(this, void 0, void 0, function* () { 16 | rpc_validator_1.RpcValidator.validateUrl(url); 17 | rpc_validator_1.RpcValidator.validateMethod(method); 18 | rpc_validator_1.RpcValidator.validateId(id); 19 | const q = new neon_js_1.rpc.Query({ method, params, id }); 20 | return yield q.execute(url, requestConfig); 21 | }); 22 | } 23 | } 24 | exports.RpcDelegate = RpcDelegate; 25 | //# sourceMappingURL=rpc-delegate.js.map -------------------------------------------------------------------------------- /dist/delegates/rpc-delegate.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"rpc-delegate.js","sourceRoot":"","sources":["../../src/delegates/rpc-delegate.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,iDAAyC;AACzC,+DAA0D;AAG1D,MAAa,WAAW;IACtB,MAAM,CAAO,KAAK,CAAC,GAAW,EAAE,MAAc,EAAE,MAAa,EAAE,EAAU,EAAE,aAAiC;;YAC1G,4BAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAA;YAC7B,4BAAY,CAAC,cAAc,CAAC,MAAM,CAAC,CAAA;YACnC,4BAAY,CAAC,UAAU,CAAC,EAAE,CAAC,CAAA;YAE3B,MAAM,CAAC,GAAG,IAAI,aAAG,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;YAC/C,OAAO,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,aAAa,CAAC,CAAA;QAC5C,CAAC;KAAA;CACF;AATD,kCASC"} -------------------------------------------------------------------------------- /dist/helpers/block-helper.d.ts: -------------------------------------------------------------------------------- 1 | export declare class BlockHelper { 2 | static getGenerationTime(block: object, previousBlock: object | undefined): number; 3 | static getTransactionCount(block: any): number; 4 | } 5 | -------------------------------------------------------------------------------- /dist/helpers/block-helper.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const lodash_1 = require("lodash"); 4 | class BlockHelper { 5 | static getGenerationTime(block, previousBlock) { 6 | if (previousBlock && previousBlock.time) { 7 | return block.time - previousBlock.time; 8 | } 9 | else { 10 | return 0; 11 | } 12 | } 13 | static getTransactionCount(block) { 14 | if (block && block.tx && lodash_1.isArray(block.tx)) { 15 | return block.tx.length; 16 | } 17 | return 0; 18 | } 19 | } 20 | exports.BlockHelper = BlockHelper; 21 | //# sourceMappingURL=block-helper.js.map -------------------------------------------------------------------------------- /dist/helpers/block-helper.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"block-helper.js","sourceRoot":"","sources":["../../src/helpers/block-helper.ts"],"names":[],"mappings":";;AAAA,mCAAgC;AAEhC,MAAa,WAAW;IACtB,MAAM,CAAC,iBAAiB,CAAC,KAAa,EAAE,aAAiC;QACvE,IAAI,aAAa,IAAK,aAAqB,CAAC,IAAI,EAAE;YAChD,OAAQ,KAAa,CAAC,IAAI,GAAI,aAAqB,CAAC,IAAI,CAAA;SACzD;aAAM;YACL,OAAO,CAAC,CAAA;SACT;IACH,CAAC;IAED,MAAM,CAAC,mBAAmB,CAAC,KAAU;QACnC,IAAI,KAAK,IAAI,KAAK,CAAC,EAAE,IAAI,gBAAO,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE;YAC1C,OAAO,KAAK,CAAC,EAAE,CAAC,MAAM,CAAA;SACvB;QACD,OAAO,CAAC,CAAA;IACV,CAAC;CACF;AAfD,kCAeC"} -------------------------------------------------------------------------------- /dist/neo.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { EventEmitter } from 'events'; 3 | import { LoggerOptions } from 'node-log-it'; 4 | import { Mesh, MeshOptions } from './core/mesh'; 5 | import { NodeOptions } from './core/node'; 6 | import { Api, ApiOptions } from './core/api'; 7 | import { Syncer, SyncerOptions } from './core/syncer'; 8 | import { MemoryStorage, MemoryStorageOptions } from './storages/memory-storage'; 9 | import { MongodbStorage, MongodbStorageOptions } from './storages/mongodb-storage'; 10 | import { BlockAnalyzer, BlockAnalyzerOptions } from './analyzers/block-analyzer'; 11 | export interface NeoOptions { 12 | network?: string; 13 | storageType?: string; 14 | endpoints?: object[]; 15 | enableSyncer?: boolean; 16 | enableBlockAnalyzer?: boolean; 17 | nodeOptions?: NodeOptions; 18 | meshOptions?: MeshOptions; 19 | storageOptions?: MemoryStorageOptions | MongodbStorageOptions; 20 | apiOptions?: ApiOptions; 21 | syncerOptions?: SyncerOptions; 22 | blockAnalyzerOptions?: BlockAnalyzerOptions; 23 | loggerOptions?: LoggerOptions; 24 | } 25 | export declare class Neo extends EventEmitter { 26 | mesh: Mesh; 27 | storage?: MemoryStorage | MongodbStorage; 28 | api: Api; 29 | syncer?: Syncer; 30 | blockAnalyzer?: BlockAnalyzer; 31 | private options; 32 | private logger; 33 | constructor(options?: NeoOptions); 34 | static readonly VERSION: string; 35 | static readonly UserAgent: string; 36 | close(): void; 37 | private validateOptionalParameters; 38 | private getMesh; 39 | private getStorage; 40 | private getApi; 41 | private getSyncer; 42 | private getBlockAnalyzer; 43 | private getNodes; 44 | } 45 | -------------------------------------------------------------------------------- /dist/neo.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 | const events_1 = require("events"); 7 | const node_log_it_1 = require("node-log-it"); 8 | const lodash_1 = require("lodash"); 9 | const mesh_1 = require("./core/mesh"); 10 | const node_1 = require("./core/node"); 11 | const api_1 = require("./core/api"); 12 | const syncer_1 = require("./core/syncer"); 13 | const memory_storage_1 = require("./storages/memory-storage"); 14 | const mongodb_storage_1 = require("./storages/mongodb-storage"); 15 | const block_analyzer_1 = require("./analyzers/block-analyzer"); 16 | const endpoint_validator_1 = require("./validators/endpoint-validator"); 17 | const profiles_1 = __importDefault(require("./common/profiles")); 18 | const constants_1 = __importDefault(require("./common/constants")); 19 | const version = require('../package.json').version; 20 | const MODULE_NAME = 'Neo'; 21 | const DEFAULT_OPTIONS = { 22 | network: constants_1.default.network.testnet, 23 | enableSyncer: true, 24 | enableBlockAnalyzer: false, 25 | loggerOptions: {}, 26 | }; 27 | class Neo extends events_1.EventEmitter { 28 | constructor(options = {}) { 29 | super(); 30 | this.options = lodash_1.merge({}, DEFAULT_OPTIONS, options); 31 | this.validateOptionalParameters(); 32 | this.logger = new node_log_it_1.Logger(MODULE_NAME, this.options.loggerOptions); 33 | this.logger.info('Version:', Neo.VERSION); 34 | this.mesh = this.getMesh(); 35 | this.storage = this.getStorage(); 36 | this.api = this.getApi(); 37 | this.syncer = this.getSyncer(); 38 | this.blockAnalyzer = this.getBlockAnalyzer(); 39 | this.logger.debug('constructor completes.'); 40 | } 41 | static get VERSION() { 42 | return version; 43 | } 44 | static get UserAgent() { 45 | return `NEO-JS:${Neo.VERSION}`; 46 | } 47 | close() { 48 | this.logger.debug('close triggered.'); 49 | if (this.syncer) { 50 | this.syncer.close(); 51 | } 52 | if (this.mesh) { 53 | this.mesh.close(); 54 | } 55 | if (this.storage) { 56 | this.storage.close(); 57 | } 58 | if (this.api) { 59 | this.api.close(); 60 | } 61 | if (this.blockAnalyzer) { 62 | this.blockAnalyzer.close(); 63 | } 64 | } 65 | validateOptionalParameters() { 66 | } 67 | getMesh() { 68 | this.logger.debug('getMesh triggered.'); 69 | const nodes = this.getNodes(); 70 | return new mesh_1.Mesh(nodes, this.options.meshOptions); 71 | } 72 | getStorage() { 73 | this.logger.debug('getStorage triggered.'); 74 | if (!this.options.storageType) { 75 | return undefined; 76 | } 77 | else if (this.options.storageType === constants_1.default.storage.memory) { 78 | return new memory_storage_1.MemoryStorage(this.options.storageOptions); 79 | } 80 | else if (this.options.storageType === constants_1.default.storage.mongodb) { 81 | const mongoStorageOptions = lodash_1.merge({}, this.options.storageOptions, { userAgent: Neo.UserAgent }); 82 | return new mongodb_storage_1.MongodbStorage(mongoStorageOptions); 83 | } 84 | else { 85 | throw new Error(`Unknown storageType [${this.options.storageType}]`); 86 | } 87 | } 88 | getApi() { 89 | this.logger.debug('getApi triggered.'); 90 | return new api_1.Api(this.mesh, this.storage, this.options.apiOptions); 91 | } 92 | getSyncer() { 93 | this.logger.debug('getSyncer triggered.'); 94 | if (this.options.enableSyncer) { 95 | return new syncer_1.Syncer(this.mesh, this.storage, this.options.syncerOptions); 96 | } 97 | else { 98 | return undefined; 99 | } 100 | } 101 | getBlockAnalyzer() { 102 | this.logger.debug('getBlockAnalyzer triggered.'); 103 | if (this.options.enableBlockAnalyzer) { 104 | return new block_analyzer_1.BlockAnalyzer(this.storage, this.options.blockAnalyzerOptions); 105 | } 106 | else { 107 | return undefined; 108 | } 109 | } 110 | getNodes() { 111 | this.logger.debug('getNodes triggered.'); 112 | let endpoints = []; 113 | if (this.options.endpoints) { 114 | endpoint_validator_1.EndpointValidator.validateArray(this.options.endpoints); 115 | endpoints = this.options.endpoints; 116 | } 117 | else if (this.options.network === constants_1.default.network.testnet) { 118 | endpoints = profiles_1.default.rpc.testnet; 119 | } 120 | else if (this.options.network === constants_1.default.network.mainnet) { 121 | endpoints = profiles_1.default.rpc.mainnet; 122 | } 123 | else { 124 | throw new Error('Invalid network or provided endpoints.'); 125 | } 126 | const nodes = []; 127 | endpoints.forEach((item) => { 128 | const endpoint = item.endpoint; 129 | const node = new node_1.Node(endpoint, this.options.nodeOptions); 130 | nodes.push(node); 131 | }); 132 | return nodes; 133 | } 134 | } 135 | exports.Neo = Neo; 136 | //# sourceMappingURL=neo.js.map -------------------------------------------------------------------------------- /dist/neo.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"neo.js","sourceRoot":"","sources":["../src/neo.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/storages/memory-storage.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { EventEmitter } from 'events'; 3 | import { LoggerOptions } from 'node-log-it'; 4 | export interface MemoryStorageOptions { 5 | loggerOptions?: LoggerOptions; 6 | } 7 | export declare class MemoryStorage extends EventEmitter { 8 | private _isReady; 9 | private _blockHeight?; 10 | private blockCollection; 11 | private options; 12 | private logger; 13 | constructor(options?: MemoryStorageOptions); 14 | isReady(): boolean; 15 | getBlockCount(): Promise; 16 | getHighestBlockHeight(): Promise; 17 | setBlockCount(height: number): Promise; 18 | countBlockRedundancy(height: number): Promise; 19 | getBlock(height: number): Promise; 20 | getTransaction(transactionId: string): Promise; 21 | setBlock(height: number, block: object, options?: object): Promise; 22 | pruneBlock(height: number, redundancySize: number): Promise; 23 | analyzeBlocks(startHeight: number, endHeight: number): Promise; 24 | getBlockMetaCount(): Promise; 25 | getHighestBlockMetaHeight(): Promise; 26 | getHighestBlockMeta(): Promise; 27 | setBlockMeta(blockMeta: object): Promise; 28 | setTransactionMeta(transactionMeta: object): Promise; 29 | analyzeBlockMetas(startHeight: number, endHeight: number): Promise; 30 | analyzeTransactionMetas(startHeight: number, endHeight: number): Promise; 31 | removeBlockMetaByHeight(height: number): Promise; 32 | countLegacyTransactionMeta(targetApiLevel: number): Promise; 33 | pruneLegacyTransactionMeta(targetApiLevel: number): Promise; 34 | close(): Promise; 35 | private setReady; 36 | private validateOptionalParameters; 37 | } 38 | -------------------------------------------------------------------------------- /dist/storages/memory-storage.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | Object.defineProperty(exports, "__esModule", { value: true }); 11 | const events_1 = require("events"); 12 | const node_log_it_1 = require("node-log-it"); 13 | const lodash_1 = require("lodash"); 14 | const MODULE_NAME = 'MemoryStorage'; 15 | const DEFAULT_OPTIONS = { 16 | loggerOptions: {}, 17 | }; 18 | class MemoryStorage extends events_1.EventEmitter { 19 | constructor(options = {}) { 20 | super(); 21 | this._isReady = false; 22 | this.blockCollection = []; 23 | this.options = lodash_1.merge({}, DEFAULT_OPTIONS, options); 24 | this.validateOptionalParameters(); 25 | this.logger = new node_log_it_1.Logger(MODULE_NAME, this.options.loggerOptions); 26 | this.setReady(); 27 | this.logger.debug('constructor completes.'); 28 | } 29 | isReady() { 30 | return this._isReady; 31 | } 32 | getBlockCount() { 33 | return __awaiter(this, void 0, void 0, function* () { 34 | throw new Error('getBlockCount() method is deprecated. Please use getHighestBlockHeight() instead.'); 35 | }); 36 | } 37 | getHighestBlockHeight() { 38 | return __awaiter(this, void 0, void 0, function* () { 39 | if (this._blockHeight) { 40 | return this._blockHeight; 41 | } 42 | else { 43 | throw new Error('blockHeight unavailable'); 44 | } 45 | }); 46 | } 47 | setBlockCount(height) { 48 | return __awaiter(this, void 0, void 0, function* () { 49 | this._blockHeight = height; 50 | }); 51 | } 52 | countBlockRedundancy(height) { 53 | return __awaiter(this, void 0, void 0, function* () { 54 | throw new Error('Not implemented.'); 55 | }); 56 | } 57 | getBlock(height) { 58 | return __awaiter(this, void 0, void 0, function* () { 59 | const blockItem = lodash_1.find(this.blockCollection, { height }); 60 | if (blockItem) { 61 | return blockItem.block; 62 | } 63 | else { 64 | throw new Error('Block not found.'); 65 | } 66 | }); 67 | } 68 | getTransaction(transactionId) { 69 | return __awaiter(this, void 0, void 0, function* () { 70 | throw new Error('Not implemented.'); 71 | }); 72 | } 73 | setBlock(height, block, options = {}) { 74 | return __awaiter(this, void 0, void 0, function* () { 75 | this.blockCollection.push({ height, block }); 76 | }); 77 | } 78 | pruneBlock(height, redundancySize) { 79 | return __awaiter(this, void 0, void 0, function* () { 80 | throw new Error('Not implemented.'); 81 | }); 82 | } 83 | analyzeBlocks(startHeight, endHeight) { 84 | return __awaiter(this, void 0, void 0, function* () { 85 | throw new Error('Not implemented.'); 86 | }); 87 | } 88 | getBlockMetaCount() { 89 | return __awaiter(this, void 0, void 0, function* () { 90 | throw new Error('Not implemented.'); 91 | }); 92 | } 93 | getHighestBlockMetaHeight() { 94 | return __awaiter(this, void 0, void 0, function* () { 95 | throw new Error('Not implemented.'); 96 | }); 97 | } 98 | getHighestBlockMeta() { 99 | return __awaiter(this, void 0, void 0, function* () { 100 | throw new Error('Not implemented.'); 101 | }); 102 | } 103 | setBlockMeta(blockMeta) { 104 | return __awaiter(this, void 0, void 0, function* () { 105 | throw new Error('Not implemented.'); 106 | }); 107 | } 108 | setTransactionMeta(transactionMeta) { 109 | return __awaiter(this, void 0, void 0, function* () { 110 | throw new Error('Not implemented.'); 111 | }); 112 | } 113 | analyzeBlockMetas(startHeight, endHeight) { 114 | return __awaiter(this, void 0, void 0, function* () { 115 | throw new Error('Not implemented.'); 116 | }); 117 | } 118 | analyzeTransactionMetas(startHeight, endHeight) { 119 | return __awaiter(this, void 0, void 0, function* () { 120 | throw new Error('Not implemented.'); 121 | }); 122 | } 123 | removeBlockMetaByHeight(height) { 124 | return __awaiter(this, void 0, void 0, function* () { 125 | throw new Error('Not implemented.'); 126 | }); 127 | } 128 | countLegacyTransactionMeta(targetApiLevel) { 129 | return __awaiter(this, void 0, void 0, function* () { 130 | throw new Error('Not implemented.'); 131 | }); 132 | } 133 | pruneLegacyTransactionMeta(targetApiLevel) { 134 | return __awaiter(this, void 0, void 0, function* () { 135 | throw new Error('Not implemented.'); 136 | }); 137 | } 138 | close() { 139 | return __awaiter(this, void 0, void 0, function* () { 140 | this.logger.debug('close triggered.'); 141 | }); 142 | } 143 | setReady() { 144 | this._isReady = true; 145 | this.emit('ready'); 146 | } 147 | validateOptionalParameters() { 148 | } 149 | } 150 | exports.MemoryStorage = MemoryStorage; 151 | //# sourceMappingURL=memory-storage.js.map -------------------------------------------------------------------------------- /dist/storages/memory-storage.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"memory-storage.js","sourceRoot":"","sources":["../../src/storages/memory-storage.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/storages/mongodb-storage.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | import { EventEmitter } from 'events'; 3 | import { LoggerOptions } from 'node-log-it'; 4 | export interface MongodbStorageOptions { 5 | connectOnInit?: boolean; 6 | reviewIndexesOnConnect?: boolean; 7 | connectionString?: string; 8 | userAgent?: string; 9 | collectionNames?: { 10 | blocks?: string; 11 | blockMetas?: string; 12 | transactionMetas?: string; 13 | }; 14 | loggerOptions?: LoggerOptions; 15 | } 16 | export declare class MongodbStorage extends EventEmitter { 17 | private _isReady; 18 | private blockDao; 19 | private blockMetaDao; 20 | private transactionMetaDao; 21 | private options; 22 | private logger; 23 | constructor(options?: MongodbStorageOptions); 24 | isReady(): boolean; 25 | getBlockCount(): Promise; 26 | getHighestBlockHeight(): Promise; 27 | setBlockCount(height: number): Promise; 28 | countBlockRedundancy(height: number): Promise; 29 | getBlock(height: number): Promise; 30 | getBlocks(height: number): Promise; 31 | getTransaction(transactionId: string): Promise; 32 | setBlock(height: number, block: object, options?: object): Promise; 33 | pruneBlock(height: number, redundancySize: number): Promise; 34 | analyzeBlocks(startHeight: number, endHeight: number): Promise; 35 | getBlockMetaCount(): Promise; 36 | getHighestBlockMetaHeight(): Promise; 37 | setBlockMeta(blockMeta: object): Promise; 38 | setTransactionMeta(transactionMeta: object): Promise; 39 | analyzeBlockMetas(startHeight: number, endHeight: number): Promise; 40 | analyzeTransactionMetas(startHeight: number, endHeight: number): Promise; 41 | removeBlockMetaByHeight(height: number): Promise; 42 | countLegacyTransactionMeta(targetApiLevel: number): Promise; 43 | pruneLegacyTransactionMeta(targetApiLevel: number): Promise; 44 | close(): Promise; 45 | private readyHandler; 46 | private validateOptionalParameters; 47 | private initConnection; 48 | private setReady; 49 | private reviewIndexes; 50 | private reviewBlockIndexForHeight; 51 | private reviewBlockIndexForTransactionId; 52 | private reviewBlockMetaIndexForHeight; 53 | private reviewBlockMetaIndexForTime; 54 | private reviewTransactionMetaIndexForHeight; 55 | private reviewTransactionMetaIndexForTime; 56 | private reviewTransactionMetaIndexForTransactionId; 57 | private reviewTransactionMetaIndexForType; 58 | } 59 | -------------------------------------------------------------------------------- /dist/storages/mongodb-storage.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"mongodb-storage.js","sourceRoot":"","sources":["../../src/storages/mongodb-storage.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/storages/mongodb/block-dao.d.ts: -------------------------------------------------------------------------------- 1 | import { Mongoose } from 'mongoose'; 2 | export declare class BlockDao { 3 | private model; 4 | constructor(mongoose: Mongoose, collectionName: string); 5 | countByHeight(height: number): Promise; 6 | getHighestHeight(): Promise; 7 | getByHeight(height: number): Promise; 8 | listByHeight(height: number): Promise; 9 | getByTransactionId(transactionId: string): Promise; 10 | save(data: object): Promise; 11 | deleteManyById(id: string): Promise; 12 | analyze(startHeight: number, endHeight: number): Promise; 13 | reviewIndex(key: string, keyObj: object): Promise; 14 | private getModel; 15 | } 16 | -------------------------------------------------------------------------------- /dist/storages/mongodb/block-dao.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | Object.defineProperty(exports, "__esModule", { value: true }); 11 | const schemas_1 = require("./schemas"); 12 | const utils_1 = require("./utils"); 13 | class BlockDao { 14 | constructor(mongoose, collectionName) { 15 | this.model = this.getModel(mongoose, collectionName); 16 | } 17 | countByHeight(height) { 18 | return __awaiter(this, void 0, void 0, function* () { 19 | return yield this.model.countDocuments({ height }).exec(); 20 | }); 21 | } 22 | getHighestHeight() { 23 | return __awaiter(this, void 0, void 0, function* () { 24 | const doc = yield this.model 25 | .findOne({}, 'height') 26 | .sort({ height: -1 }) 27 | .exec(); 28 | return doc.height; 29 | }); 30 | } 31 | getByHeight(height) { 32 | return __awaiter(this, void 0, void 0, function* () { 33 | return yield this.model 34 | .findOne({ height }) 35 | .sort({ createdAt: -1 }) 36 | .exec(); 37 | }); 38 | } 39 | listByHeight(height) { 40 | return __awaiter(this, void 0, void 0, function* () { 41 | const result = yield this.model 42 | .find({ height }) 43 | .sort({ createdAt: -1 }) 44 | .exec(); 45 | if (!result) { 46 | return []; 47 | } 48 | return result; 49 | }); 50 | } 51 | getByTransactionId(transactionId) { 52 | return __awaiter(this, void 0, void 0, function* () { 53 | return yield this.model 54 | .findOne({ 55 | 'payload.tx': { 56 | $elemMatch: { 57 | txid: transactionId, 58 | }, 59 | }, 60 | }) 61 | .exec(); 62 | }); 63 | } 64 | save(data) { 65 | return __awaiter(this, void 0, void 0, function* () { 66 | yield this.model(data).save(); 67 | }); 68 | } 69 | deleteManyById(id) { 70 | return __awaiter(this, void 0, void 0, function* () { 71 | yield this.model.deleteMany({ _id: id }).exec(); 72 | }); 73 | } 74 | analyze(startHeight, endHeight) { 75 | return __awaiter(this, void 0, void 0, function* () { 76 | const aggregatorOptions = [ 77 | { 78 | $group: { 79 | _id: '$height', 80 | count: { $sum: 1 }, 81 | }, 82 | }, 83 | { 84 | $match: { 85 | _id: { 86 | $gte: startHeight, 87 | $lte: endHeight, 88 | }, 89 | }, 90 | }, 91 | ]; 92 | return yield this.model 93 | .aggregate(aggregatorOptions) 94 | .allowDiskUse(true) 95 | .exec(); 96 | }); 97 | } 98 | reviewIndex(key, keyObj) { 99 | return __awaiter(this, void 0, void 0, function* () { 100 | return yield utils_1.MongodbUtils.reviewIndex(this.model, key, keyObj); 101 | }); 102 | } 103 | getModel(mongoose, collectionName) { 104 | const schema = schemas_1.blockSchema; 105 | return mongoose.models[collectionName] || mongoose.model(collectionName, schema); 106 | } 107 | } 108 | exports.BlockDao = BlockDao; 109 | //# sourceMappingURL=block-dao.js.map -------------------------------------------------------------------------------- /dist/storages/mongodb/block-dao.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"block-dao.js","sourceRoot":"","sources":["../../../src/storages/mongodb/block-dao.ts"],"names":[],"mappings":";;;;;;;;;;AACA,uCAAuC;AACvC,mCAAsC;AAEtC,MAAa,QAAQ;IAGnB,YAAY,QAAkB,EAAE,cAAsB;QACpD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;IACtD,CAAC;IAEK,aAAa,CAAC,MAAc;;YAChC,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QAC3D,CAAC;KAAA;IAEK,gBAAgB;;YACpB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK;iBACzB,OAAO,CAAC,EAAE,EAAE,QAAQ,CAAC;iBACrB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;iBACpB,IAAI,EAAE,CAAA;YACT,OAAO,GAAG,CAAC,MAAM,CAAA;QACnB,CAAC;KAAA;IAEK,WAAW,CAAC,MAAc;;YAK9B,OAAO,MAAM,IAAI,CAAC,KAAK;iBACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;iBACnB,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC;iBACvB,IAAI,EAAE,CAAA;QACX,CAAC;KAAA;IAEK,YAAY,CAAC,MAAc;;YAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK;iBAC5B,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;iBAChB,IAAI,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC;iBACvB,IAAI,EAAE,CAAA;YACT,IAAI,CAAC,MAAM,EAAE;gBACX,OAAO,EAAE,CAAA;aACV;YAED,OAAO,MAAM,CAAA;QACf,CAAC;KAAA;IAEK,kBAAkB,CAAC,aAAqB;;YAC5C,OAAO,MAAM,IAAI,CAAC,KAAK;iBACpB,OAAO,CAAC;gBACP,YAAY,EAAE;oBACZ,UAAU,EAAE;wBACV,IAAI,EAAE,aAAa;qBACpB;iBACF;aACF,CAAC;iBACD,IAAI,EAAE,CAAA;QACX,CAAC;KAAA;IAEK,IAAI,CAAC,IAAY;;YACrB,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;QAC/B,CAAC;KAAA;IAEK,cAAc,CAAC,EAAU;;YAC7B,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACjD,CAAC;KAAA;IAEK,OAAO,CAAC,WAAmB,EAAE,SAAiB;;YASlD,MAAM,iBAAiB,GAAG;gBACxB;oBACE,MAAM,EAAE;wBACN,GAAG,EAAE,SAAS;wBACd,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE;qBACnB;iBACF;gBACD;oBACE,MAAM,EAAE;wBACN,GAAG,EAAE;4BAEH,IAAI,EAAE,WAAW;4BACjB,IAAI,EAAE,SAAS;yBAChB;qBACF;iBACF;aACF,CAAA;YACD,OAAO,MAAM,IAAI,CAAC,KAAK;iBACpB,SAAS,CAAC,iBAAiB,CAAC;iBAC5B,YAAY,CAAC,IAAI,CAAC;iBAClB,IAAI,EAAE,CAAA;QACX,CAAC;KAAA;IAEK,WAAW,CAAC,GAAW,EAAE,MAAc;;YAC3C,OAAO,MAAM,oBAAY,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QAChE,CAAC;KAAA;IAEO,QAAQ,CAAC,QAAkB,EAAE,cAAsB;QACzD,MAAM,MAAM,GAAG,qBAAW,CAAA;QAC1B,OAAO,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;IAClF,CAAC;CACF;AAtGD,4BAsGC"} -------------------------------------------------------------------------------- /dist/storages/mongodb/block-meta-dao.d.ts: -------------------------------------------------------------------------------- 1 | import { Mongoose } from 'mongoose'; 2 | export declare class BlockMetaDao { 3 | private model; 4 | constructor(mongoose: Mongoose, collectionName: string); 5 | count(): Promise; 6 | getHighest(): Promise; 7 | getHighestHeight(): Promise; 8 | save(data: object): Promise; 9 | removeByHeight(height: number): Promise; 10 | analyze(startHeight: number, endHeight: number): Promise; 11 | reviewIndex(key: string, keyObj: object): Promise; 12 | private getModel; 13 | } 14 | -------------------------------------------------------------------------------- /dist/storages/mongodb/block-meta-dao.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | Object.defineProperty(exports, "__esModule", { value: true }); 11 | const schemas_1 = require("./schemas"); 12 | const utils_1 = require("./utils"); 13 | class BlockMetaDao { 14 | constructor(mongoose, collectionName) { 15 | this.model = this.getModel(mongoose, collectionName); 16 | } 17 | count() { 18 | return __awaiter(this, void 0, void 0, function* () { 19 | return yield this.model.countDocuments({}).exec(); 20 | }); 21 | } 22 | getHighest() { 23 | return __awaiter(this, void 0, void 0, function* () { 24 | return yield this.model 25 | .findOne() 26 | .sort({ height: -1 }) 27 | .exec(); 28 | }); 29 | } 30 | getHighestHeight() { 31 | return __awaiter(this, void 0, void 0, function* () { 32 | try { 33 | const doc = yield this.getHighest(); 34 | return doc.height; 35 | } 36 | catch (err) { 37 | return 0; 38 | } 39 | }); 40 | } 41 | save(data) { 42 | return __awaiter(this, void 0, void 0, function* () { 43 | return yield this.model(data).save(); 44 | }); 45 | } 46 | removeByHeight(height) { 47 | return __awaiter(this, void 0, void 0, function* () { 48 | return yield this.model.deleteMany({ height }).exec(); 49 | }); 50 | } 51 | analyze(startHeight, endHeight) { 52 | return __awaiter(this, void 0, void 0, function* () { 53 | return yield this.model 54 | .find({ 55 | height: { 56 | $gte: startHeight, 57 | $lte: endHeight, 58 | }, 59 | }, 'height apiLevel') 60 | .exec(); 61 | }); 62 | } 63 | reviewIndex(key, keyObj) { 64 | return __awaiter(this, void 0, void 0, function* () { 65 | return yield utils_1.MongodbUtils.reviewIndex(this.model, key, keyObj); 66 | }); 67 | } 68 | getModel(mongoose, collectionName) { 69 | const schema = schemas_1.blockMetaSchema; 70 | return mongoose.models[collectionName] || mongoose.model(collectionName, schema); 71 | } 72 | } 73 | exports.BlockMetaDao = BlockMetaDao; 74 | //# sourceMappingURL=block-meta-dao.js.map -------------------------------------------------------------------------------- /dist/storages/mongodb/block-meta-dao.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"block-meta-dao.js","sourceRoot":"","sources":["../../../src/storages/mongodb/block-meta-dao.ts"],"names":[],"mappings":";;;;;;;;;;AACA,uCAA2C;AAC3C,mCAAsC;AAEtC,MAAa,YAAY;IAGvB,YAAY,QAAkB,EAAE,cAAsB;QACpD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;IACtD,CAAC;IAEK,KAAK;;YACT,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACnD,CAAC;KAAA;IAEK,UAAU;;YACd,OAAO,MAAM,IAAI,CAAC,KAAK;iBACpB,OAAO,EAAE;iBACT,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC;iBACpB,IAAI,EAAE,CAAA;QACX,CAAC;KAAA;IAEK,gBAAgB;;YAEpB,IAAI;gBACF,MAAM,GAAG,GAAQ,MAAM,IAAI,CAAC,UAAU,EAAE,CAAA;gBACxC,OAAO,GAAG,CAAC,MAAM,CAAA;aAClB;YAAC,OAAO,GAAG,EAAE;gBACZ,OAAO,CAAC,CAAA;aACT;QACH,CAAC;KAAA;IAEK,IAAI,CAAC,IAAY;;YACrB,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;QACtC,CAAC;KAAA;IAEK,cAAc,CAAC,MAAc;;YACjC,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACvD,CAAC;KAAA;IAEK,OAAO,CAAC,WAAmB,EAAE,SAAiB;;YASlD,OAAO,MAAM,IAAI,CAAC,KAAK;iBACpB,IAAI,CACH;gBACE,MAAM,EAAE;oBACN,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,SAAS;iBAChB;aACF,EACD,iBAAiB,CAClB;iBACA,IAAI,EAAE,CAAA;QACX,CAAC;KAAA;IAEK,WAAW,CAAC,GAAW,EAAE,MAAc;;YAC3C,OAAO,MAAM,oBAAY,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QAChE,CAAC;KAAA;IAEO,QAAQ,CAAC,QAAkB,EAAE,cAAsB;QACzD,MAAM,MAAM,GAAG,yBAAe,CAAA;QAC9B,OAAO,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;IAClF,CAAC;CACF;AAlED,oCAkEC"} -------------------------------------------------------------------------------- /dist/storages/mongodb/schemas.d.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from 'mongoose'; 2 | export declare const blockSchema: Schema; 3 | export declare const blockMetaSchema: Schema; 4 | export declare const transactionMetaSchema: Schema; 5 | -------------------------------------------------------------------------------- /dist/storages/mongodb/schemas.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | const mongoose_1 = require("mongoose"); 4 | exports.blockSchema = new mongoose_1.Schema({ 5 | height: Number, 6 | createdBy: String, 7 | source: String, 8 | userAgent: String, 9 | payload: { 10 | hash: String, 11 | size: Number, 12 | version: Number, 13 | previousblockhash: String, 14 | merkleroot: String, 15 | time: Number, 16 | index: { type: 'Number', required: true }, 17 | nonce: String, 18 | nextconsensus: String, 19 | script: { 20 | invocation: String, 21 | verification: String, 22 | }, 23 | tx: [], 24 | confirmations: Number, 25 | nextblockhash: String, 26 | }, 27 | }, { timestamps: true }); 28 | exports.blockMetaSchema = new mongoose_1.Schema({ 29 | height: { type: 'Number', unique: true, required: true, dropDups: true }, 30 | time: Number, 31 | size: Number, 32 | generationTime: Number, 33 | transactionCount: Number, 34 | createdBy: String, 35 | apiLevel: Number, 36 | }, { timestamps: true }); 37 | exports.transactionMetaSchema = new mongoose_1.Schema({ 38 | height: Number, 39 | time: Number, 40 | transactionId: { type: 'String', unique: true, required: true, dropDups: true }, 41 | type: String, 42 | size: Number, 43 | networkFee: Number, 44 | systemFee: Number, 45 | voutCount: Number, 46 | vinCount: Number, 47 | createdBy: String, 48 | apiLevel: Number, 49 | }, { timestamps: true }); 50 | //# sourceMappingURL=schemas.js.map -------------------------------------------------------------------------------- /dist/storages/mongodb/schemas.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../../src/storages/mongodb/schemas.ts"],"names":[],"mappings":";;AAAA,uCAAiC;AAEpB,QAAA,WAAW,GAAG,IAAI,iBAAM,CACnC;IACE,MAAM,EAAE,MAAM;IACd,SAAS,EAAE,MAAM;IACjB,MAAM,EAAE,MAAM;IACd,SAAS,EAAE,MAAM;IACjB,OAAO,EAAE;QACP,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,MAAM;QACZ,OAAO,EAAE,MAAM;QACf,iBAAiB,EAAE,MAAM;QACzB,UAAU,EAAE,MAAM;QAClB,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE;QACzC,KAAK,EAAE,MAAM;QACb,aAAa,EAAE,MAAM;QACrB,MAAM,EAAE;YACN,UAAU,EAAE,MAAM;YAClB,YAAY,EAAE,MAAM;SACrB;QACD,EAAE,EAAE,EAAE;QACN,aAAa,EAAE,MAAM;QACrB,aAAa,EAAE,MAAM;KACtB;CACF,EACD,EAAE,UAAU,EAAE,IAAI,EAAE,CACrB,CAAA;AAEY,QAAA,eAAe,GAAG,IAAI,iBAAM,CACvC;IACE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;IACxE,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,cAAc,EAAE,MAAM;IACtB,gBAAgB,EAAE,MAAM;IACxB,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,MAAM;CACjB,EACD,EAAE,UAAU,EAAE,IAAI,EAAE,CACrB,CAAA;AAEY,QAAA,qBAAqB,GAAG,IAAI,iBAAM,CAC7C;IACE,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,MAAM;IACZ,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;IAC/E,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,MAAM;IAClB,SAAS,EAAE,MAAM;IACjB,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,MAAM;IAChB,SAAS,EAAE,MAAM;IACjB,QAAQ,EAAE,MAAM;CACjB,EACD,EAAE,UAAU,EAAE,IAAI,EAAE,CACrB,CAAA"} -------------------------------------------------------------------------------- /dist/storages/mongodb/transaction-meta-dao.d.ts: -------------------------------------------------------------------------------- 1 | import { Mongoose } from 'mongoose'; 2 | export declare class TransactionMetaDao { 3 | private model; 4 | constructor(mongoose: Mongoose, collectionName: string); 5 | count(): Promise; 6 | save(data: object): Promise; 7 | countByBelowApiLevel(apiLevel: number): Promise; 8 | removeByBelowApiLevel(apiLevel: number): Promise; 9 | analyze(startHeight: number, endHeight: number): Promise; 10 | reviewIndex(key: string, keyObj: object): Promise; 11 | private getModel; 12 | } 13 | -------------------------------------------------------------------------------- /dist/storages/mongodb/transaction-meta-dao.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | Object.defineProperty(exports, "__esModule", { value: true }); 11 | const schemas_1 = require("./schemas"); 12 | const utils_1 = require("./utils"); 13 | class TransactionMetaDao { 14 | constructor(mongoose, collectionName) { 15 | this.model = this.getModel(mongoose, collectionName); 16 | } 17 | count() { 18 | return __awaiter(this, void 0, void 0, function* () { 19 | return yield this.model.countDocuments({}).exec(); 20 | }); 21 | } 22 | save(data) { 23 | return __awaiter(this, void 0, void 0, function* () { 24 | return yield this.model(data).save(); 25 | }); 26 | } 27 | countByBelowApiLevel(apiLevel) { 28 | return __awaiter(this, void 0, void 0, function* () { 29 | return yield this.model 30 | .countDocuments({ 31 | apiLevel: { $lt: apiLevel }, 32 | }) 33 | .exec(); 34 | }); 35 | } 36 | removeByBelowApiLevel(apiLevel) { 37 | return __awaiter(this, void 0, void 0, function* () { 38 | return yield this.model 39 | .deleteMany({ 40 | apiLevel: { $lt: apiLevel }, 41 | }) 42 | .exec(); 43 | }); 44 | } 45 | analyze(startHeight, endHeight) { 46 | return __awaiter(this, void 0, void 0, function* () { 47 | return yield this.model 48 | .find({ 49 | height: { 50 | $gte: startHeight, 51 | $lte: endHeight, 52 | }, 53 | }, 'height apiLevel') 54 | .exec(); 55 | }); 56 | } 57 | reviewIndex(key, keyObj) { 58 | return __awaiter(this, void 0, void 0, function* () { 59 | return yield utils_1.MongodbUtils.reviewIndex(this.model, key, keyObj); 60 | }); 61 | } 62 | getModel(mongoose, collectionName) { 63 | const schema = schemas_1.transactionMetaSchema; 64 | return mongoose.models[collectionName] || mongoose.model(collectionName, schema); 65 | } 66 | } 67 | exports.TransactionMetaDao = TransactionMetaDao; 68 | //# sourceMappingURL=transaction-meta-dao.js.map -------------------------------------------------------------------------------- /dist/storages/mongodb/transaction-meta-dao.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"transaction-meta-dao.js","sourceRoot":"","sources":["../../../src/storages/mongodb/transaction-meta-dao.ts"],"names":[],"mappings":";;;;;;;;;;AACA,uCAAiD;AACjD,mCAAsC;AAEtC,MAAa,kBAAkB;IAG7B,YAAY,QAAkB,EAAE,cAAsB;QACpD,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAA;IACtD,CAAC;IAEK,KAAK;;YACT,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA;QACnD,CAAC;KAAA;IAEK,IAAI,CAAC,IAAY;;YACrB,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;QACtC,CAAC;KAAA;IAEK,oBAAoB,CAAC,QAAgB;;YACzC,OAAO,MAAM,IAAI,CAAC,KAAK;iBACpB,cAAc,CAAC;gBACd,QAAQ,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;aAC5B,CAAC;iBACD,IAAI,EAAE,CAAA;QACX,CAAC;KAAA;IAEK,qBAAqB,CAAC,QAAgB;;YAC1C,OAAO,MAAM,IAAI,CAAC,KAAK;iBACpB,UAAU,CAAC;gBACV,QAAQ,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE;aAC5B,CAAC;iBACD,IAAI,EAAE,CAAA;QACX,CAAC;KAAA;IAEK,OAAO,CAAC,WAAmB,EAAE,SAAiB;;YASlD,OAAO,MAAM,IAAI,CAAC,KAAK;iBACpB,IAAI,CACH;gBACE,MAAM,EAAE;oBACN,IAAI,EAAE,WAAW;oBACjB,IAAI,EAAE,SAAS;iBAChB;aACF,EACD,iBAAiB,CAClB;iBACA,IAAI,EAAE,CAAA;QACX,CAAC;KAAA;IAEK,WAAW,CAAC,GAAW,EAAE,MAAc;;YAC3C,OAAO,MAAM,oBAAY,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,CAAA;QAChE,CAAC;KAAA;IAEO,QAAQ,CAAC,QAAkB,EAAE,cAAsB;QACzD,MAAM,MAAM,GAAG,+BAAqB,CAAA;QACpC,OAAO,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,cAAc,EAAE,MAAM,CAAC,CAAA;IAClF,CAAC;CACF;AA7DD,gDA6DC"} -------------------------------------------------------------------------------- /dist/storages/mongodb/utils.d.ts: -------------------------------------------------------------------------------- 1 | export declare class MongodbUtils { 2 | static reviewIndex(model: any, key: string, keyObj: object): Promise; 3 | static hasIndex(model: any, key: string): Promise; 4 | static createIndex(model: any, keyObj: object): Promise; 5 | } 6 | -------------------------------------------------------------------------------- /dist/storages/mongodb/utils.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { 3 | return new (P || (P = Promise))(function (resolve, reject) { 4 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } 5 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } 6 | function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } 7 | step((generator = generator.apply(thisArg, _arguments || [])).next()); 8 | }); 9 | }; 10 | Object.defineProperty(exports, "__esModule", { value: true }); 11 | const lodash_1 = require("lodash"); 12 | class MongodbUtils { 13 | static reviewIndex(model, key, keyObj) { 14 | return __awaiter(this, void 0, void 0, function* () { 15 | const hasRequiredIndex = yield MongodbUtils.hasIndex(model, key); 16 | if (hasRequiredIndex) { 17 | return; 18 | } 19 | yield MongodbUtils.createIndex(model, keyObj); 20 | }); 21 | } 22 | static hasIndex(model, key) { 23 | return __awaiter(this, void 0, void 0, function* () { 24 | const indexes = yield model.collection.getIndexes(); 25 | const keys = Object.keys(indexes); 26 | const canFindIndex = lodash_1.includes(keys, key); 27 | return canFindIndex; 28 | }); 29 | } 30 | static createIndex(model, keyObj) { 31 | return __awaiter(this, void 0, void 0, function* () { 32 | yield model.collection.createIndex(keyObj); 33 | }); 34 | } 35 | } 36 | exports.MongodbUtils = MongodbUtils; 37 | //# sourceMappingURL=utils.js.map -------------------------------------------------------------------------------- /dist/storages/mongodb/utils.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/storages/mongodb/utils.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,mCAAiC;AAEjC,MAAa,YAAY;IACvB,MAAM,CAAO,WAAW,CAAC,KAAU,EAAE,GAAW,EAAE,MAAc;;YAC9D,MAAM,gBAAgB,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;YAChE,IAAI,gBAAgB,EAAE;gBACpB,OAAM;aACP;YACD,MAAM,YAAY,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAC/C,CAAC;KAAA;IAED,MAAM,CAAO,QAAQ,CAAC,KAAU,EAAE,GAAW;;YAC3C,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,UAAU,EAAE,CAAA;YACnD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACjC,MAAM,YAAY,GAAG,iBAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;YACxC,OAAO,YAAY,CAAA;QACrB,CAAC;KAAA;IAED,MAAM,CAAO,WAAW,CAAC,KAAU,EAAE,MAAc;;YACjD,MAAM,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,MAAM,CAAC,CAAA;QAC5C,CAAC;KAAA;CACF;AAnBD,oCAmBC"} -------------------------------------------------------------------------------- /dist/validators/endpoint-validator.d.ts: -------------------------------------------------------------------------------- 1 | export declare class EndpointValidator { 2 | static validateArray(endpoints: object[]): void; 3 | } 4 | -------------------------------------------------------------------------------- /dist/validators/endpoint-validator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | class EndpointValidator { 4 | static validateArray(endpoints) { 5 | if (endpoints.length <= 0) { 6 | throw new Error(`'endpoints' must be an non empty array.`); 7 | } 8 | endpoints.forEach((ep) => { 9 | if (!ep.endpoint) { 10 | throw new Error(`item of 'endpoints' contain 'endpoint' property.`); 11 | } 12 | }); 13 | } 14 | } 15 | exports.EndpointValidator = EndpointValidator; 16 | //# sourceMappingURL=endpoint-validator.js.map -------------------------------------------------------------------------------- /dist/validators/endpoint-validator.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"endpoint-validator.js","sourceRoot":"","sources":["../../src/validators/endpoint-validator.ts"],"names":[],"mappings":";;AAAA,MAAa,iBAAiB;IAC5B,MAAM,CAAC,aAAa,CAAC,SAAmB;QACtC,IAAI,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE;YACzB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;SAC3D;QACD,SAAS,CAAC,OAAO,CAAC,CAAC,EAAO,EAAE,EAAE;YAC5B,IAAI,CAAC,EAAE,CAAC,QAAQ,EAAE;gBAChB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAA;aACpE;QACH,CAAC,CAAC,CAAA;IACJ,CAAC;CACF;AAXD,8CAWC"} -------------------------------------------------------------------------------- /dist/validators/mongodb-validator.d.ts: -------------------------------------------------------------------------------- 1 | export declare class MongodbValidator { 2 | static validateConnectionString(connectionString: string): void; 3 | } 4 | -------------------------------------------------------------------------------- /dist/validators/mongodb-validator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | class MongodbValidator { 4 | static validateConnectionString(connectionString) { 5 | } 6 | } 7 | exports.MongodbValidator = MongodbValidator; 8 | //# sourceMappingURL=mongodb-validator.js.map -------------------------------------------------------------------------------- /dist/validators/mongodb-validator.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"mongodb-validator.js","sourceRoot":"","sources":["../../src/validators/mongodb-validator.ts"],"names":[],"mappings":";;AAEA,MAAa,gBAAgB;IAC3B,MAAM,CAAC,wBAAwB,CAAC,gBAAwB;IAExD,CAAC;CACF;AAJD,4CAIC"} -------------------------------------------------------------------------------- /dist/validators/neo-validator.d.ts: -------------------------------------------------------------------------------- 1 | export declare class NeoValidator { 2 | static validateHeight(height: number): void; 3 | static validateTransactionId(transactionId: string): void; 4 | } 5 | -------------------------------------------------------------------------------- /dist/validators/neo-validator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | class NeoValidator { 4 | static validateHeight(height) { 5 | if (height <= 0) { 6 | throw new Error(`'height' must be an integer 1 or above.`); 7 | } 8 | } 9 | static validateTransactionId(transactionId) { 10 | } 11 | } 12 | exports.NeoValidator = NeoValidator; 13 | //# sourceMappingURL=neo-validator.js.map -------------------------------------------------------------------------------- /dist/validators/neo-validator.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"neo-validator.js","sourceRoot":"","sources":["../../src/validators/neo-validator.ts"],"names":[],"mappings":";;AAAA,MAAa,YAAY;IACvB,MAAM,CAAC,cAAc,CAAC,MAAc;QAClC,IAAI,MAAM,IAAI,CAAC,EAAE;YACf,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;SAC3D;IACH,CAAC;IAED,MAAM,CAAC,qBAAqB,CAAC,aAAqB;IAElD,CAAC;CACF;AAVD,oCAUC"} -------------------------------------------------------------------------------- /dist/validators/rpc-validator.d.ts: -------------------------------------------------------------------------------- 1 | export declare class RpcValidator { 2 | static validateUrl(url: string): void; 3 | static validateMethod(method: string): void; 4 | static validateId(id: number): void; 5 | } 6 | -------------------------------------------------------------------------------- /dist/validators/rpc-validator.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | Object.defineProperty(exports, "__esModule", { value: true }); 3 | class RpcValidator { 4 | static validateUrl(url) { 5 | } 6 | static validateMethod(method) { 7 | } 8 | static validateId(id) { 9 | } 10 | } 11 | exports.RpcValidator = RpcValidator; 12 | //# sourceMappingURL=rpc-validator.js.map -------------------------------------------------------------------------------- /dist/validators/rpc-validator.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"rpc-validator.js","sourceRoot":"","sources":["../../src/validators/rpc-validator.ts"],"names":[],"mappings":";;AAEA,MAAa,YAAY;IACvB,MAAM,CAAC,WAAW,CAAC,GAAW;IAE9B,CAAC;IAED,MAAM,CAAC,cAAc,CAAC,MAAc;IAEpC,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,EAAU;IAE5B,CAAC;CACF;AAZD,oCAYC"} -------------------------------------------------------------------------------- /docs/assets/images/icons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CityOfZion/neo-js/ccc7eae8924c98f051486ee7cdb5f415bf1c392c/docs/assets/images/icons.png -------------------------------------------------------------------------------- /docs/assets/images/icons@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CityOfZion/neo-js/ccc7eae8924c98f051486ee7cdb5f415bf1c392c/docs/assets/images/icons@2x.png -------------------------------------------------------------------------------- /docs/assets/images/widgets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CityOfZion/neo-js/ccc7eae8924c98f051486ee7cdb5f415bf1c392c/docs/assets/images/widgets.png -------------------------------------------------------------------------------- /docs/assets/images/widgets@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CityOfZion/neo-js/ccc7eae8924c98f051486ee7cdb5f415bf1c392c/docs/assets/images/widgets@2x.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cityofzion/neo-js", 3 | "description": "Running NEO blockchain full node with Node.js and MongoDB.", 4 | "version": "0.15.0-dev", 5 | "license": "MIT", 6 | "main": "dist/neo", 7 | "types": "dist/neo", 8 | "engines": { 9 | "node": ">=8.0.0" 10 | }, 11 | "homepage": "https://github.com/CityOfZion/neo-js#readme", 12 | "repository": { 13 | "type": "git", 14 | "url": "git+https://github.com/CityOfZion/neo-js.git" 15 | }, 16 | "bugs": { 17 | "url": "https://github.com/CityOfZion/neo-js/issues" 18 | }, 19 | "scripts": { 20 | "mocha": "mocha", 21 | "tsc": "tsc", 22 | "tslint": "tslint", 23 | "prettier": "prettier", 24 | "typedoc": "typedoc", 25 | "dev": "tsc --watch", 26 | "clean": "rm -rf ./dist", 27 | "build": "npm run clean && tsc", 28 | "build:docs": "typedoc --out ./docs --mode modules ./src", 29 | "rebuild": "rm -rf ./node_modules && npm install && npm run build", 30 | "rebuild:hard": "rm -f ./package-lock.json && npm run rebuild", 31 | "lint": "tslint -c tslint.json './src/**/*.ts'", 32 | "format": "prettier --write './src/**/*.ts'", 33 | "test": "mocha --reporter spec", 34 | "version:minor": "npm version minor", 35 | "version:patch": "npm version patch" 36 | }, 37 | "dependencies": { 38 | "@cityofzion/neon-js": "^4.3.0", 39 | "async": "^2.6.1", 40 | "events": "^3.0.0", 41 | "lodash": "^4.17.10", 42 | "mongoose": "^5.3.15", 43 | "node-log-it": "^2.0.0" 44 | }, 45 | "devDependencies": { 46 | "@types/async": "^2.0.50", 47 | "@types/chance": "^1.0.1", 48 | "@types/events": "^1.2.0", 49 | "@types/mongodb": "^3.1.17", 50 | "@types/mongoose": "^5.3.3", 51 | "@types/node": "^10.7.1", 52 | "chai": "^4.1.2", 53 | "mocha": "^5.2.0", 54 | "prettier": "^1.15.1", 55 | "tslint": "^5.11.0", 56 | "tslint-config-prettier": "^1.15.0", 57 | "typedoc": "^0.13.0", 58 | "typescript": "^3.1.1" 59 | }, 60 | "keywords": [ 61 | "neo", 62 | "antshares", 63 | "blockchain", 64 | "cryptocurrency" 65 | ] 66 | } 67 | -------------------------------------------------------------------------------- /src/common/constants.ts: -------------------------------------------------------------------------------- 1 | const C = { 2 | network: { 3 | testnet: 'testnet', 4 | mainnet: 'mainnet', 5 | }, 6 | storage: { 7 | memory: 'memory', 8 | mongodb: 'mongodb', 9 | }, 10 | rpc: { 11 | getblock: 'getblock', 12 | getblockcount: 'getblockcount', 13 | getversion: 'getversion', 14 | getrawtransaction: 'getrawtransaction', 15 | }, 16 | transaction: { 17 | MinerTransaction: 'MinerTransaction', 18 | ContractTransaction: 'ContractTransaction', 19 | InvocationTransaction: 'InvocationTransaction', 20 | ClaimTransaction: 'ClaimTransaction', 21 | }, 22 | } 23 | 24 | export default C 25 | -------------------------------------------------------------------------------- /src/common/profiles.ts: -------------------------------------------------------------------------------- 1 | const profiles = { 2 | rpc: { 3 | mainnet: [ 4 | { endpoint: 'https://seed1.switcheo.network:10331' }, 5 | { endpoint: 'https://seed2.switcheo.network:10331' }, 6 | { endpoint: 'https://seed3.switcheo.network:10331' }, 7 | { endpoint: 'https://seed4.switcheo.network:10331' }, 8 | { endpoint: 'https://seed5.switcheo.network:10331' }, 9 | { endpoint: 'https://seed1.cityofzion.io:443' }, 10 | { endpoint: 'https://seed2.cityofzion.io:443' }, 11 | { endpoint: 'https://seed3.cityofzion.io:443' }, 12 | { endpoint: 'https://seed4.cityofzion.io:443' }, 13 | { endpoint: 'https://seed5.cityofzion.io:443' }, 14 | { endpoint: 'https://seed6.cityofzion.io:443' }, 15 | { endpoint: 'https://seed7.cityofzion.io:443' }, 16 | { endpoint: 'https://seed8.cityofzion.io:443' }, 17 | { endpoint: 'https://seed9.cityofzion.io:443' }, 18 | { endpoint: 'https://seed0.cityofzion.io:443' }, 19 | { endpoint: 'http://node1.ams2.bridgeprotocol.io' }, 20 | { endpoint: 'http://node2.ams2.bridgeprotocol.io' }, 21 | { endpoint: 'http://node1.nyc3.bridgeprotocol.io' }, 22 | { endpoint: 'http://node2.nyc3.bridgeprotocol.io' }, 23 | { endpoint: 'http://node1.sgp1.bridgeprotocol.io' }, 24 | { endpoint: 'http://node2.sgp1.bridgeprotocol.io' }, 25 | { endpoint: 'https://seed1.redpulse.com:443' }, 26 | { endpoint: 'https://seed2.redpulse.com:443' }, 27 | { endpoint: 'http://seed1.aphelion-neo.com:10332' }, 28 | { endpoint: 'http://seed2.aphelion-neo.com:10332' }, 29 | { endpoint: 'http://seed3.aphelion-neo.com:10332' }, 30 | { endpoint: 'http://seed4.aphelion-neo.com:10332' }, 31 | { endpoint: 'http://seed1.ngd.network:10332' }, 32 | { endpoint: 'http://seed2.ngd.network:10332' }, 33 | { endpoint: 'http://seed3.ngd.network:10332' }, 34 | { endpoint: 'http://seed4.ngd.network:10332' }, 35 | { endpoint: 'http://seed5.ngd.network:10332' }, 36 | { endpoint: 'http://seed6.ngd.network:10332' }, 37 | { endpoint: 'http://seed7.ngd.network:10332' }, 38 | { endpoint: 'http://seed8.ngd.network:10332' }, 39 | { endpoint: 'http://seed9.ngd.network:10332' }, 40 | { endpoint: 'http://seed10.ngd.network:10332' }, 41 | ], 42 | testnet: [ 43 | { endpoint: 'https://test1.cityofzion.io:443' }, 44 | { endpoint: 'https://test2.cityofzion.io:443' }, 45 | { endpoint: 'https://test3.cityofzion.io:443' }, 46 | { endpoint: 'https://test4.cityofzion.io:443' }, 47 | { endpoint: 'https://test5.cityofzion.io:443' }, 48 | ], 49 | }, 50 | assets: [ 51 | { id: '0xc56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b', name: 'NEO', symbol: 'NEO', type: 'GoverningToken', precision: 0 }, 52 | { id: '0x602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7', name: 'GAS', symbol: 'GAS', type: 'UtilityToken', precision: 8 }, 53 | ], 54 | } 55 | 56 | export default profiles 57 | -------------------------------------------------------------------------------- /src/core/api.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | import { Logger, LoggerOptions } from 'node-log-it' 3 | import { merge } from 'lodash' 4 | import { Mesh } from './mesh' 5 | import { NodeMeta } from './node' 6 | import { MemoryStorage } from '../storages/memory-storage' 7 | import { MongodbStorage } from '../storages/mongodb-storage' 8 | import C from '../common/constants' 9 | import { NeoValidator } from '../validators/neo-validator' 10 | 11 | const MODULE_NAME = 'Api' 12 | const DEFAULT_OPTIONS: ApiOptions = { 13 | insertToStorage: true, 14 | checkReadyIntervalMs: 200, 15 | loggerOptions: {}, 16 | } 17 | 18 | export interface ApiOptions { 19 | insertToStorage?: boolean 20 | checkReadyIntervalMs?: number 21 | loggerOptions?: LoggerOptions 22 | } 23 | 24 | interface StorageInsertPayload { 25 | method: string 26 | nodeMeta: NodeMeta | undefined 27 | result: any 28 | } 29 | 30 | export class Api extends EventEmitter { 31 | private mesh: Mesh 32 | private storage?: MemoryStorage | MongodbStorage 33 | private options: ApiOptions 34 | private logger: Logger 35 | private checkReadyIntervalId?: NodeJS.Timer 36 | 37 | constructor(mesh: Mesh, storage?: MemoryStorage | MongodbStorage, options: ApiOptions = {}) { 38 | super() 39 | 40 | // Associate required properties 41 | this.mesh = mesh 42 | this.storage = storage 43 | 44 | // Associate optional properties 45 | this.options = merge({}, DEFAULT_OPTIONS, options) 46 | this.validateOptionalParameters() 47 | 48 | // Bootstrapping 49 | this.logger = new Logger(MODULE_NAME, this.options.loggerOptions) 50 | this.checkMeshAndStorageReady() 51 | 52 | // Event handlers 53 | this.on('storage:insert', this.storageInsertHandler.bind(this)) 54 | 55 | this.logger.debug('constructor completes.') 56 | } 57 | 58 | async getBlockCount(): Promise { 59 | this.logger.debug('getBlockCount triggered.') 60 | if (!this.storage) { 61 | this.logger.debug('No storage delegate detected.') 62 | return this.getBlockCountFromMesh() 63 | } 64 | 65 | let blockHeight: number | undefined 66 | try { 67 | blockHeight = await this.storage!.getHighestBlockHeight() 68 | return blockHeight 69 | } catch (err) { 70 | // Suppress error and continue 71 | } 72 | 73 | // Failed to fetch from storage, try mesh instead 74 | this.logger.debug('Cannot find result from storage delegate, attempt to fetch from mesh instead...') 75 | blockHeight = await this.getBlockCountFromMesh() 76 | this.logger.debug('Successfully fetch result from mesh.') 77 | this.emit('storage:insert', { method: C.rpc.getblockcount, result: blockHeight }) 78 | return blockHeight 79 | } 80 | 81 | async getBlock(height: number): Promise { 82 | this.logger.debug('getBlock triggered. height:', height) 83 | 84 | NeoValidator.validateHeight(height) 85 | 86 | if (!this.storage) { 87 | this.logger.debug('No storage delegate detected.') 88 | return this.getBlockFromMesh(height) 89 | } 90 | 91 | let block: object | undefined 92 | try { 93 | block = await this.storage!.getBlock(height) 94 | return block 95 | } catch (err) { 96 | // Suppress error and continue 97 | this.logger.debug('Cannot find result from storage delegate. Error:', err.message) 98 | } 99 | 100 | // Failed to fetch from storage, try mesh instead 101 | this.logger.debug('Attempt to fetch from mesh instead...') 102 | const blockResponse: any = await this.getBlockAndNodeMetaFromMesh(height) 103 | this.logger.debug('Successfully fetch result from mesh.') 104 | block = blockResponse.block 105 | const nodeMeta = blockResponse.nodeMeta 106 | this.emit('storage:insert', { method: C.rpc.getblock, result: { height, block }, nodeMeta }) 107 | return block! 108 | } 109 | 110 | async getTransaction(transactionId: string): Promise { 111 | this.logger.debug('getBlock triggered. transactionId:', transactionId) 112 | 113 | NeoValidator.validateTransactionId(transactionId) 114 | 115 | if (!this.storage) { 116 | this.logger.debug('No storage delegate detected.') 117 | return this.getTransactionFromMesh(transactionId) 118 | } 119 | 120 | let transaction: object | undefined 121 | try { 122 | transaction = await this.storage!.getTransaction(transactionId) 123 | return transaction 124 | } catch (err) { 125 | // Suppress error and continue 126 | this.logger.debug('Cannot find result from storage delegate. Error:', err.message) 127 | } 128 | 129 | // Failed to fetch from storage, try mesh instead 130 | this.logger.debug('Attempt to fetch from mesh instead...') 131 | transaction = await this.getTransactionFromMesh(transactionId) 132 | return transaction 133 | } 134 | 135 | close() { 136 | clearInterval(this.checkReadyIntervalId!) 137 | } 138 | 139 | private storageInsertHandler(payload: StorageInsertPayload) { 140 | if (!this.options.insertToStorage) { 141 | return 142 | } 143 | 144 | this.logger.debug('storageInsertHandler triggered.') 145 | if (payload.method === C.rpc.getblockcount) { 146 | this.storeBlockCount(payload) 147 | } else if (payload.method === C.rpc.getblock) { 148 | this.storeBlock(payload) 149 | } else { 150 | // TODO 151 | throw new Error('Not implemented.') 152 | } 153 | } 154 | 155 | private validateOptionalParameters() { 156 | // TODO 157 | } 158 | 159 | private checkMeshAndStorageReady() { 160 | this.logger.debug('checkMeshAndStorageReady triggered.') 161 | 162 | /** 163 | * The easiest implementation to asynchronously detects readiness 164 | * of multiple components, is to just periodically ping them until 165 | * all are stated to be ready. 166 | */ 167 | this.checkReadyIntervalId = setInterval(() => { 168 | const meshReady = this.mesh.isReady() 169 | const storageReady = this.storage ? this.storage.isReady() : true 170 | if (meshReady && storageReady) { 171 | this.emit('ready') 172 | clearInterval(this.checkReadyIntervalId!) 173 | } 174 | }, this.options.checkReadyIntervalMs!) 175 | } 176 | 177 | private storeBlockCount(payload: StorageInsertPayload) { 178 | if (this.storage) { 179 | const blockHeight = payload.result as number 180 | this.storage.setBlockCount(blockHeight) 181 | } 182 | } 183 | 184 | private storeBlock(payload: StorageInsertPayload) { 185 | if (this.storage) { 186 | const height = payload.result.height as number 187 | const block = payload.result.block as object 188 | const source = payload.nodeMeta ? payload.nodeMeta.endpoint : 'api:storeBlock' 189 | this.storage.setBlock(height, block, { source }) 190 | } 191 | } 192 | 193 | private async getBlockCountFromMesh(): Promise { 194 | this.logger.debug('getBlockCountFromMesh triggered.') 195 | 196 | const highestNode = this.mesh.getHighestNode() 197 | if (highestNode && highestNode.blockHeight) { 198 | return highestNode.blockHeight 199 | } else { 200 | // TODO 201 | throw new Error('Edge case not implemented.') 202 | } 203 | } 204 | 205 | private async getBlockFromMesh(height: number): Promise { 206 | this.logger.debug('getBlockFromMesh triggered.') 207 | 208 | const blockResponse: any = await this.getBlockAndNodeMetaFromMesh(height) 209 | return blockResponse.block 210 | } 211 | 212 | private async getBlockAndNodeMetaFromMesh(height: number): Promise { 213 | this.logger.debug('getBlockAndNodeMetaFromMesh triggered.') 214 | 215 | const highestNode = this.mesh.getHighestNode() 216 | if (highestNode && highestNode.blockHeight) { 217 | const nodeMeta = highestNode.getNodeMeta() 218 | const block = await highestNode.getBlock(height) 219 | return { block, nodeMeta } 220 | } else { 221 | // TODO 222 | throw new Error('Edge case not implemented.') 223 | } 224 | } 225 | 226 | private async getTransactionFromMesh(transactionId: string): Promise { 227 | this.logger.debug('getTransactionFromMesh triggered.') 228 | 229 | const highestNode = this.mesh.getHighestNode() 230 | if (highestNode && highestNode.blockHeight) { 231 | const transaction = await highestNode.getTransaction(transactionId) 232 | return transaction 233 | } else { 234 | // TODO 235 | throw new Error('Edge case not implemented.') 236 | } 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /src/core/mesh.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | import { Logger, LoggerOptions } from 'node-log-it' 3 | import { merge, filter, minBy, maxBy, random, find } from 'lodash' 4 | import { Node } from './node' 5 | 6 | const MODULE_NAME = 'Mesh' 7 | const DEFAULT_OPTIONS: MeshOptions = { 8 | startBenchmarkOnInit: true, 9 | toFetchUserAgent: true, 10 | benchmarkIntervalMs: 2000, 11 | fetchMissingUserAgentIntervalMs: 5000, 12 | refreshUserAgentIntervalMs: 5 * 60 * 1000, 13 | minActiveNodesRequired: 2, 14 | pendingRequestsThreshold: 5, 15 | loggerOptions: {}, 16 | } 17 | 18 | export interface MeshOptions { 19 | startBenchmarkOnInit?: boolean 20 | toFetchUserAgent?: boolean 21 | benchmarkIntervalMs?: number 22 | fetchMissingUserAgentIntervalMs?: number 23 | refreshUserAgentIntervalMs?: number 24 | minActiveNodesRequired?: number 25 | pendingRequestsThreshold?: number 26 | loggerOptions?: LoggerOptions 27 | } 28 | 29 | export class Mesh extends EventEmitter { 30 | nodes: Node[] // Ensure there's at least 1 item in the array 31 | 32 | private _isReady = false 33 | private benchmarkIntervalId?: NodeJS.Timer 34 | private fetchMissingUserAgentIntervalId?: NodeJS.Timer 35 | private refreshUserAgentIntervalId?: NodeJS.Timer 36 | private options: MeshOptions 37 | private logger: Logger 38 | 39 | constructor(nodes: Node[], options: MeshOptions = {}) { 40 | super() 41 | 42 | // Associate required properties 43 | this.nodes = nodes 44 | if (this.nodes.length === 0) { 45 | throw new Error('Mesh must have 1 or more nodes.') 46 | } 47 | 48 | // Associate optional properties 49 | this.options = merge({}, DEFAULT_OPTIONS, options) 50 | this.validateOptionalParameters() 51 | 52 | // Bootstrapping 53 | this.logger = new Logger(MODULE_NAME, this.options.loggerOptions) 54 | if (this.options.startBenchmarkOnInit) { 55 | this.startBenchmark() 56 | } 57 | 58 | this.logger.debug('constructor completes.') 59 | } 60 | 61 | isReady(): boolean { 62 | return this._isReady 63 | } 64 | 65 | startBenchmark() { 66 | this.logger.debug('startBenchmark triggered.') 67 | 68 | // Go through and ping all unknown nodes 69 | const unknownNodes = filter(this.nodes, (n: Node) => n.isActive === undefined) 70 | this.logger.debug('unknownNodes.length:', unknownNodes.length) 71 | unknownNodes.forEach((n: Node) => { 72 | n.getBlockCount() 73 | .then(() => { 74 | this.checkMeshReady() 75 | }) 76 | .catch((err: any) => { 77 | this.logger.info('node.getBlockCount() failed, but to continue. Endpoint:', n.endpoint, 'Message:', err.message) 78 | }) 79 | }) 80 | 81 | // Fetch node version 82 | if (this.options.toFetchUserAgent) { 83 | unknownNodes.forEach((n: Node) => { 84 | n.getVersion().catch((err: any) => { 85 | this.logger.info('node.getVersion() failed, but to continue. Endpoint:', n.endpoint, 'Message:', err.message) 86 | }) 87 | }) 88 | 89 | this.fetchMissingUserAgentIntervalId = setInterval(() => this.performFetchMissingUserAgent(), this.options.fetchMissingUserAgentIntervalMs!) 90 | this.refreshUserAgentIntervalId = setInterval(() => this.performRefreshUserAgent(), this.options.refreshUserAgentIntervalMs!) 91 | } 92 | 93 | // Start timer 94 | this.benchmarkIntervalId = setInterval(() => this.performBenchmark(), this.options.benchmarkIntervalMs!) 95 | } 96 | 97 | stopBenchmark() { 98 | this.logger.debug('stopBenchmark triggered.') 99 | if (this.benchmarkIntervalId) { 100 | clearInterval(this.benchmarkIntervalId) 101 | } 102 | if (this.fetchMissingUserAgentIntervalId) { 103 | clearInterval(this.fetchMissingUserAgentIntervalId) 104 | } 105 | if (this.refreshUserAgentIntervalId) { 106 | clearInterval(this.refreshUserAgentIntervalId) 107 | } 108 | } 109 | 110 | close() { 111 | this.logger.debug('close triggered.') 112 | this.stopBenchmark() 113 | this.nodes.forEach((n: Node) => { 114 | n.close() 115 | }) 116 | } 117 | 118 | getFastestNode(activeOnly = true): Node | undefined { 119 | this.logger.debug('getFastestNode triggered.') 120 | 121 | let nodePool = activeOnly ? this.listActiveNodes() : this.nodes 122 | if (nodePool.length === 0) { 123 | return undefined 124 | } 125 | 126 | nodePool = filter(nodePool, (n: Node) => n.latency !== undefined) 127 | if (nodePool.length === 0) { 128 | return undefined 129 | } 130 | 131 | return minBy(nodePool, 'latency') 132 | } 133 | 134 | getHighestNode(activeOnly = true): Node | undefined { 135 | this.logger.debug('getHighestNode triggered.') 136 | 137 | let nodePool = activeOnly ? this.listActiveNodes() : this.nodes 138 | if (nodePool.length === 0) { 139 | return undefined 140 | } 141 | 142 | nodePool = filter(nodePool, (n: Node) => n.blockHeight !== undefined) 143 | if (nodePool.length === 0) { 144 | return undefined 145 | } 146 | 147 | return maxBy(nodePool, 'blockHeight') 148 | } 149 | 150 | /** 151 | * @param activeOnly Toggle to only pick node that is determined to be active. 152 | */ 153 | getRandomNode(activeOnly = true): Node | undefined { 154 | this.logger.debug('getRandomNode triggered.') 155 | 156 | const nodePool = activeOnly ? this.listActiveNodes() : this.nodes 157 | if (nodePool.length === 0) { 158 | return undefined 159 | } 160 | 161 | const randomIndex = random(0, nodePool.length - 1) 162 | return nodePool[randomIndex] 163 | } 164 | 165 | /** 166 | * An optimal node is defined as a fast node that has not exceed a pending threshold. 167 | */ 168 | getOptimalNode(height: number, activeOnly = true): Node | undefined { 169 | this.logger.debug('getOptimalNode triggered.') 170 | 171 | const nodePool = activeOnly ? this.listActiveNodes() : this.nodes 172 | if (nodePool.length === 0) { 173 | return undefined 174 | } 175 | 176 | // Filter nodes that has the required height 177 | const qualifyHeightNodes = filter(this.nodes, (n: Node) => n.blockHeight !== undefined && n.blockHeight >= height) 178 | if (qualifyHeightNodes.length === 0) { 179 | return undefined 180 | } 181 | 182 | // Filter nodes that exceed pending threshold 183 | const qualifyPendingNodes = filter(qualifyHeightNodes, (n: Node) => !n.pendingRequests || n.pendingRequests <= this.options.pendingRequestsThreshold!) 184 | if (qualifyPendingNodes.length === 0) { 185 | // If all qualify nodes exceeded pending threshold, then just pick a random one from qualifyHeightNodes 186 | const randomIndex = random(0, qualifyHeightNodes.length - 1) 187 | return qualifyHeightNodes[randomIndex] 188 | } 189 | 190 | // Pick the fastest node from qualifyPendingNodes 191 | return minBy(qualifyPendingNodes, 'latency') 192 | } 193 | 194 | private validateOptionalParameters() { 195 | // TODO 196 | } 197 | 198 | private performBenchmark() { 199 | this.logger.debug('performBenchmark triggered.') 200 | const node = this.getNodeToBenchmark() 201 | if (node) { 202 | node.getBlockCount().catch((err: any) => { 203 | this.logger.info('node.getBlockCount error in performBenchmark(). Endpoint:', node.endpoint, 'Message:', err.message) 204 | }) 205 | } else { 206 | this.logger.info('Unable to find a suitable node to perform benchmark.') 207 | } 208 | } 209 | 210 | private getNodeToBenchmark(): Node | undefined { 211 | this.logger.debug('getNodeToBenchmark triggered.') 212 | 213 | // Find nodes that's not currently running benchmarks 214 | const nodePool = filter(this.nodes, (n: Node) => !n.isBenchmarking) 215 | if (nodePool.length === 0) { 216 | return undefined 217 | } 218 | 219 | // Attempt to find a node that hasn't been benchmarked at all 220 | const unknownNode = find(nodePool, (n: Node) => n.lastPingTimestamp === undefined) 221 | if (unknownNode) { 222 | return unknownNode 223 | } 224 | 225 | // Attempt to find a node that last benchmark longest ago 226 | const targetNode = minBy(nodePool, (n: Node) => n.lastPingTimestamp) 227 | return targetNode 228 | } 229 | 230 | private performFetchMissingUserAgent() { 231 | this.logger.debug('performBenchmark triggered.') 232 | const nodePool = filter(this.nodes, (n: Node) => n.userAgent === undefined) 233 | nodePool.forEach((n: Node) => { 234 | n.getVersion().catch((err: any) => { 235 | this.logger.info('node.getVersion() failed, but to continue. Endpoint:', n.endpoint, 'Message:', err.message) 236 | }) 237 | }) 238 | } 239 | 240 | private performRefreshUserAgent() { 241 | this.logger.debug('performRefreshUserAgent triggered.') 242 | this.nodes.forEach((n: Node) => { 243 | n.getVersion().catch((err: any) => { 244 | this.logger.info('node.getVersion() failed, but to continue. Endpoint:', n.endpoint, 'Message:', err.message) 245 | }) 246 | }) 247 | } 248 | 249 | private checkMeshReady() { 250 | this.logger.debug('checkMeshReady triggered.') 251 | const activeNodes = this.listActiveNodes() 252 | if (!this.options.minActiveNodesRequired || activeNodes.length >= this.options.minActiveNodesRequired) { 253 | if (!this._isReady) { 254 | // First signal that mesh is considered as 'ready' state 255 | this.setReady() 256 | this.logger.debug('mesh is considered to be now ready.') 257 | } 258 | } 259 | } 260 | 261 | private setReady() { 262 | this._isReady = true 263 | this.emit('ready') 264 | } 265 | 266 | private listActiveNodes(): Node[] { 267 | return filter(this.nodes, { isActive: true }) 268 | } 269 | } 270 | -------------------------------------------------------------------------------- /src/core/node.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | import { Logger, LoggerOptions } from 'node-log-it' 3 | import { merge, filter, remove, meanBy, round } from 'lodash' 4 | import { RpcDelegate } from '../delegates/rpc-delegate' 5 | import C from '../common/constants' 6 | import { NeoValidator } from '../validators/neo-validator' 7 | import { AxiosRequestConfig } from 'axios' 8 | 9 | const MODULE_NAME = 'Node' 10 | const DEFAULT_ID = 0 11 | const DEFAULT_OPTIONS: NodeOptions = { 12 | toLogReliability: false, 13 | truncateRequestLogIntervalMs: 30 * 1000, 14 | requestLogTtl: 5 * 60 * 1000, // In milliseconds 15 | timeout: 30000, 16 | loggerOptions: {}, 17 | } 18 | 19 | export interface NodeMeta { 20 | isActive: boolean | undefined 21 | pendingRequests: number | undefined 22 | latency: number | undefined 23 | blockHeight: number | undefined 24 | lastSeenTimestamp: number | undefined 25 | userAgent: string | undefined 26 | endpoint: string 27 | } 28 | 29 | export interface NodeOptions { 30 | toLogReliability?: boolean 31 | truncateRequestLogIntervalMs?: number 32 | requestLogTtl?: number 33 | timeout?: number 34 | loggerOptions?: LoggerOptions 35 | } 36 | 37 | export class Node extends EventEmitter { 38 | isActive: boolean | undefined 39 | pendingRequests: number | undefined 40 | latency: number | undefined // In milliseconds 41 | blockHeight: number | undefined 42 | lastPingTimestamp: number | undefined // Latest timestamp that node perform benchmark on 43 | lastSeenTimestamp: number | undefined // Latest timestamp that node detected to be activated via benchmark 44 | userAgent: string | undefined 45 | endpoint: string 46 | isBenchmarking = false 47 | 48 | private options: NodeOptions 49 | private logger: Logger 50 | private requestLogs: object[] = [] 51 | private truncateRequestLogIntervalId?: NodeJS.Timer 52 | 53 | constructor(endpoint: string, options: NodeOptions = {}) { 54 | super() 55 | 56 | // Associate required properties 57 | this.endpoint = endpoint 58 | 59 | // Associate optional properties 60 | this.options = merge({}, DEFAULT_OPTIONS, options) 61 | this.validateOptionalParameters() 62 | 63 | // Bootstrapping 64 | this.logger = new Logger(MODULE_NAME, this.options.loggerOptions) 65 | if (this.options.toLogReliability) { 66 | this.truncateRequestLogIntervalId = setInterval(() => this.truncateRequestLog(), this.options.truncateRequestLogIntervalMs!) 67 | } 68 | 69 | // Event handlers 70 | this.on('query:init', this.queryInitHandler.bind(this)) 71 | this.on('query:complete', this.queryCompleteHandler.bind(this)) 72 | this.logger.debug('constructor completes.') 73 | } 74 | 75 | async getBlock(height: number, isVerbose: boolean = true): Promise { 76 | this.logger.debug('getBlock triggered.') 77 | 78 | NeoValidator.validateHeight(height) 79 | 80 | const verboseKey: number = isVerbose ? 1 : 0 81 | return await this.query(C.rpc.getblock, [height, verboseKey]) 82 | } 83 | 84 | async getBlockCount(): Promise { 85 | this.logger.debug('getBlockCount triggered.') 86 | return await this.query(C.rpc.getblockcount) 87 | } 88 | 89 | async getVersion(): Promise { 90 | this.logger.debug('getVersion triggered.') 91 | return await this.query(C.rpc.getversion) 92 | } 93 | 94 | async getTransaction(transactionId: string, isVerbose: boolean = true): Promise { 95 | this.logger.debug('transactionId triggered.') 96 | const verboseKey: number = isVerbose ? 1 : 0 97 | return await this.query(C.rpc.getrawtransaction, [transactionId, verboseKey]) 98 | } 99 | 100 | getNodeMeta(): NodeMeta { 101 | return { 102 | isActive: this.isActive, 103 | pendingRequests: this.pendingRequests, 104 | latency: this.latency, 105 | blockHeight: this.blockHeight, 106 | lastSeenTimestamp: this.lastSeenTimestamp, 107 | userAgent: this.userAgent, 108 | endpoint: this.endpoint, 109 | } 110 | } 111 | 112 | /** 113 | * A float number between 0 an 1 114 | */ 115 | getNodeReliability(): number | undefined { 116 | const requestCount = this.requestLogs.length 117 | if (requestCount === 0) { 118 | return undefined 119 | } 120 | 121 | const successCount = filter(this.requestLogs, (logObj: any) => logObj.isSuccess === true).length 122 | return successCount / requestCount 123 | } 124 | 125 | getShapedLatency(): number | undefined { 126 | this.logger.debug('getShapedLatency triggered.') 127 | if (this.requestLogs.length === 0) { 128 | return undefined 129 | } 130 | 131 | const logPool = filter(this.requestLogs, (logObj: any) => logObj.isSuccess === true && logObj.latency !== undefined) 132 | if (logPool.length === 0) { 133 | return undefined 134 | } 135 | 136 | const averageLatency = round(meanBy(logPool, (logObj: any) => logObj.latency), 0) 137 | return averageLatency 138 | } 139 | 140 | close() { 141 | this.logger.debug('close triggered.') 142 | if (this.truncateRequestLogIntervalId) { 143 | clearInterval(this.truncateRequestLogIntervalId) 144 | } 145 | } 146 | 147 | private queryInitHandler(payload: object) { 148 | this.logger.debug('queryInitHandler triggered.') 149 | this.startBenchmark(payload) 150 | } 151 | 152 | private queryCompleteHandler(payload: any) { 153 | this.logger.debug('queryCompleteHandler triggered.') 154 | this.stopBenchmark(payload) 155 | } 156 | 157 | private validateOptionalParameters() { 158 | // TODO 159 | } 160 | 161 | private startBenchmark(payload: any) { 162 | this.logger.debug('startBenchmark triggered.') 163 | this.increasePendingRequest() 164 | 165 | // Perform latency benchmark when it's a getBlockCount() request 166 | if (payload.method === C.rpc.getblockcount) { 167 | if (this.isBenchmarking) { 168 | this.logger.debug('An benchmarking schedule is already in place. Skipping... endpoint:', this.endpoint) 169 | } else { 170 | this.isBenchmarking = true 171 | } 172 | } 173 | } 174 | 175 | private stopBenchmark(payload: any) { 176 | this.logger.debug('stopBenchmark triggered.') 177 | this.decreasePendingRequest() 178 | this.lastPingTimestamp = Date.now() 179 | 180 | // Store latest active state base on existence of error 181 | if (!payload.isSuccess) { 182 | this.isActive = false 183 | } else { 184 | this.isActive = true 185 | this.lastSeenTimestamp = Date.now() 186 | } 187 | 188 | // Store block height value if provided 189 | if (payload.blockHeight) { 190 | this.blockHeight = payload.blockHeight 191 | } 192 | 193 | // Store user agent value if provided 194 | if (payload.userAgent) { 195 | this.userAgent = payload.userAgent 196 | } 197 | 198 | // Perform benchmark when it's a getBlockCount() request 199 | if (payload.method === C.rpc.getblockcount) { 200 | if (!this.isBenchmarking) { 201 | this.logger.debug('There are no running benchmarking schedule in place. Skipping... endpoint:', this.endpoint) 202 | } else { 203 | this.isBenchmarking = false 204 | 205 | // Store latency value if provided 206 | if (payload.latency) { 207 | this.latency = payload.latency 208 | } 209 | 210 | // Reliability logging 211 | if (this.options.toLogReliability) { 212 | if (!payload.isSuccess) { 213 | this.requestLogs.push({ 214 | timestamp: Date.now(), 215 | isSuccess: payload.isSuccess, 216 | }) 217 | } else { 218 | this.requestLogs.push({ 219 | timestamp: Date.now(), 220 | isSuccess: payload.isSuccess, 221 | latency: this.latency, 222 | }) 223 | } 224 | } 225 | } 226 | } 227 | } 228 | 229 | private truncateRequestLog() { 230 | this.logger.debug('truncateRequestLog triggered.') 231 | const cutOffTimestamp = Date.now() - this.options.requestLogTtl! 232 | this.requestLogs = remove(this.requestLogs, (logObj: any) => logObj.timestamp > cutOffTimestamp) 233 | } 234 | 235 | private async query(method: string, params: any[] = [], id: number = DEFAULT_ID): Promise { 236 | this.logger.debug('query triggered. method:', method) 237 | this.emit('query:init', { method, params, id }) 238 | const requestConfig = this.getRequestConfig() 239 | const t0 = Date.now() 240 | try { 241 | const res: any = await RpcDelegate.query(this.endpoint, method, params, id, requestConfig) 242 | const latency = Date.now() - t0 243 | const result = res.result 244 | const blockHeight = method === C.rpc.getblockcount ? result : undefined 245 | const userAgent = method === C.rpc.getversion ? result.useragent : undefined 246 | this.emit('query:complete', { isSuccess: true, method, latency, blockHeight, userAgent }) 247 | return result 248 | } catch (err) { 249 | this.emit('query:complete', { isSuccess: false, method, error: err }) 250 | throw err 251 | } 252 | } 253 | 254 | private increasePendingRequest() { 255 | this.logger.debug('increasePendingRequest triggered.') 256 | if (this.pendingRequests) { 257 | this.pendingRequests += 1 258 | } else { 259 | this.pendingRequests = 1 260 | } 261 | } 262 | 263 | private decreasePendingRequest() { 264 | this.logger.debug('decreasePendingRequest triggered.') 265 | if (this.pendingRequests) { 266 | this.pendingRequests -= 1 267 | } else { 268 | this.pendingRequests = 0 269 | } 270 | } 271 | 272 | private getRequestConfig(): AxiosRequestConfig { 273 | const config: AxiosRequestConfig = {} 274 | if (this.options.timeout) { 275 | config.timeout = this.options.timeout 276 | } 277 | return config 278 | } 279 | } 280 | -------------------------------------------------------------------------------- /src/delegates/rpc-delegate.ts: -------------------------------------------------------------------------------- 1 | import { rpc } from '@cityofzion/neon-js' 2 | import { RpcValidator } from '../validators/rpc-validator' 3 | import { AxiosRequestConfig } from 'axios' 4 | 5 | export class RpcDelegate { 6 | static async query(url: string, method: string, params: any[], id: number, requestConfig: AxiosRequestConfig): Promise { 7 | RpcValidator.validateUrl(url) 8 | RpcValidator.validateMethod(method) 9 | RpcValidator.validateId(id) 10 | 11 | const q = new rpc.Query({ method, params, id }) 12 | return await q.execute(url, requestConfig) 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/helpers/block-helper.ts: -------------------------------------------------------------------------------- 1 | import { isArray } from 'lodash' 2 | 3 | export class BlockHelper { 4 | static getGenerationTime(block: object, previousBlock: object | undefined): number { 5 | if (previousBlock && (previousBlock as any).time) { 6 | return (block as any).time - (previousBlock as any).time 7 | } else { 8 | return 0 9 | } 10 | } 11 | 12 | static getTransactionCount(block: any): number { 13 | if (block && block.tx && isArray(block.tx)) { 14 | return block.tx.length 15 | } 16 | return 0 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/neo.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | import { Logger, LoggerOptions } from 'node-log-it' 3 | import { merge } from 'lodash' 4 | import { Mesh, MeshOptions } from './core/mesh' 5 | import { Node, NodeOptions } from './core/node' 6 | import { Api, ApiOptions } from './core/api' 7 | import { Syncer, SyncerOptions } from './core/syncer' 8 | import { MemoryStorage, MemoryStorageOptions } from './storages/memory-storage' 9 | import { MongodbStorage, MongodbStorageOptions } from './storages/mongodb-storage' 10 | import { BlockAnalyzer, BlockAnalyzerOptions } from './analyzers/block-analyzer' 11 | import { EndpointValidator } from './validators/endpoint-validator' 12 | import profiles from './common/profiles' 13 | import C from './common/constants' 14 | 15 | const version = require('../package.json').version // tslint:disable-line 16 | 17 | const MODULE_NAME = 'Neo' 18 | const DEFAULT_OPTIONS: NeoOptions = { 19 | network: C.network.testnet, 20 | enableSyncer: true, 21 | enableBlockAnalyzer: false, 22 | loggerOptions: {}, 23 | } 24 | 25 | export interface NeoOptions { 26 | network?: string 27 | storageType?: string 28 | endpoints?: object[] 29 | enableSyncer?: boolean 30 | enableBlockAnalyzer?: boolean 31 | nodeOptions?: NodeOptions 32 | meshOptions?: MeshOptions 33 | storageOptions?: MemoryStorageOptions | MongodbStorageOptions 34 | apiOptions?: ApiOptions 35 | syncerOptions?: SyncerOptions 36 | blockAnalyzerOptions?: BlockAnalyzerOptions 37 | loggerOptions?: LoggerOptions 38 | } 39 | 40 | export class Neo extends EventEmitter { 41 | mesh: Mesh 42 | storage?: MemoryStorage | MongodbStorage 43 | api: Api 44 | syncer?: Syncer 45 | blockAnalyzer?: BlockAnalyzer 46 | 47 | private options: NeoOptions 48 | private logger: Logger 49 | 50 | constructor(options: NeoOptions = {}) { 51 | super() 52 | 53 | // Associate optional properties 54 | this.options = merge({}, DEFAULT_OPTIONS, options) 55 | this.validateOptionalParameters() 56 | 57 | // Bootstrapping 58 | this.logger = new Logger(MODULE_NAME, this.options.loggerOptions) 59 | this.logger.info('Version:', Neo.VERSION) 60 | this.mesh = this.getMesh() 61 | this.storage = this.getStorage() 62 | this.api = this.getApi() 63 | this.syncer = this.getSyncer() 64 | this.blockAnalyzer = this.getBlockAnalyzer() 65 | 66 | this.logger.debug('constructor completes.') 67 | } 68 | 69 | static get VERSION(): string { 70 | return version 71 | } 72 | 73 | static get UserAgent(): string { 74 | return `NEO-JS:${Neo.VERSION}` 75 | } 76 | 77 | close() { 78 | this.logger.debug('close triggered.') 79 | if (this.syncer) { 80 | this.syncer.close() 81 | } 82 | if (this.mesh) { 83 | this.mesh.close() 84 | } 85 | if (this.storage) { 86 | this.storage.close() 87 | } 88 | if (this.api) { 89 | this.api.close() 90 | } 91 | if (this.blockAnalyzer) { 92 | this.blockAnalyzer.close() 93 | } 94 | } 95 | 96 | private validateOptionalParameters() { 97 | // TODO 98 | } 99 | 100 | private getMesh(): Mesh { 101 | this.logger.debug('getMesh triggered.') 102 | const nodes = this.getNodes() 103 | return new Mesh(nodes, this.options.meshOptions) 104 | } 105 | 106 | private getStorage(): MemoryStorage | MongodbStorage | undefined { 107 | this.logger.debug('getStorage triggered.') 108 | if (!this.options.storageType) { 109 | // No storage 110 | return undefined 111 | } else if (this.options.storageType === C.storage.memory) { 112 | return new MemoryStorage(this.options.storageOptions) 113 | } else if (this.options.storageType === C.storage.mongodb) { 114 | const mongoStorageOptions = merge({}, this.options.storageOptions, { userAgent: Neo.UserAgent }) 115 | return new MongodbStorage(mongoStorageOptions) 116 | } else { 117 | throw new Error(`Unknown storageType [${this.options.storageType}]`) 118 | } 119 | } 120 | 121 | private getApi(): Api { 122 | this.logger.debug('getApi triggered.') 123 | return new Api(this.mesh, this.storage, this.options.apiOptions) 124 | } 125 | 126 | private getSyncer(): Syncer | undefined { 127 | this.logger.debug('getSyncer triggered.') 128 | if (this.options.enableSyncer) { 129 | return new Syncer(this.mesh, this.storage, this.options.syncerOptions) 130 | } else { 131 | return undefined 132 | } 133 | } 134 | 135 | private getBlockAnalyzer(): BlockAnalyzer | undefined { 136 | this.logger.debug('getBlockAnalyzer triggered.') 137 | if (this.options.enableBlockAnalyzer) { 138 | return new BlockAnalyzer(this.storage, this.options.blockAnalyzerOptions) 139 | } else { 140 | return undefined 141 | } 142 | } 143 | 144 | private getNodes(): Node[] { 145 | this.logger.debug('getNodes triggered.') 146 | // Fetch endpoints 147 | let endpoints: object[] = [] 148 | if (this.options.endpoints) { 149 | EndpointValidator.validateArray(this.options.endpoints) 150 | endpoints = this.options.endpoints 151 | } else if (this.options.network === C.network.testnet) { 152 | endpoints = profiles.rpc.testnet 153 | } else if (this.options.network === C.network.mainnet) { 154 | endpoints = profiles.rpc.mainnet 155 | } else { 156 | throw new Error('Invalid network or provided endpoints.') 157 | } 158 | 159 | // Instantiate nodes 160 | const nodes: Node[] = [] 161 | endpoints.forEach((item) => { 162 | const endpoint = (item as any).endpoint 163 | const node = new Node(endpoint, this.options.nodeOptions) 164 | nodes.push(node) 165 | }) 166 | 167 | return nodes 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /src/storages/memory-storage.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events' 2 | import { Logger, LoggerOptions } from 'node-log-it' 3 | import { merge, find } from 'lodash' 4 | 5 | const MODULE_NAME = 'MemoryStorage' 6 | const DEFAULT_OPTIONS: MemoryStorageOptions = { 7 | loggerOptions: {}, 8 | } 9 | 10 | export interface MemoryStorageOptions { 11 | loggerOptions?: LoggerOptions 12 | } 13 | 14 | interface BlockItem { 15 | height: number 16 | block: object 17 | } 18 | 19 | export class MemoryStorage extends EventEmitter { 20 | private _isReady = false 21 | private _blockHeight?: number 22 | private blockCollection: BlockItem[] = [] 23 | private options: MemoryStorageOptions 24 | private logger: Logger 25 | 26 | constructor(options: MemoryStorageOptions = {}) { 27 | super() 28 | 29 | // Associate optional properties 30 | this.options = merge({}, DEFAULT_OPTIONS, options) 31 | this.validateOptionalParameters() 32 | 33 | // Bootstrapping 34 | this.logger = new Logger(MODULE_NAME, this.options.loggerOptions) 35 | this.setReady() 36 | 37 | this.logger.debug('constructor completes.') 38 | } 39 | 40 | isReady(): boolean { 41 | return this._isReady 42 | } 43 | 44 | /** 45 | * @deprecated 46 | */ 47 | async getBlockCount(): Promise { 48 | throw new Error('getBlockCount() method is deprecated. Please use getHighestBlockHeight() instead.') 49 | } 50 | 51 | async getHighestBlockHeight(): Promise { 52 | if (this._blockHeight) { 53 | return this._blockHeight 54 | } else { 55 | throw new Error('blockHeight unavailable') 56 | } 57 | } 58 | 59 | async setBlockCount(height: number): Promise { 60 | this._blockHeight = height 61 | } 62 | 63 | async countBlockRedundancy(height: number): Promise { 64 | throw new Error('Not implemented.') 65 | } 66 | 67 | async getBlock(height: number): Promise { 68 | const blockItem = find(this.blockCollection, { height }) 69 | if (blockItem) { 70 | return blockItem.block 71 | } else { 72 | throw new Error('Block not found.') 73 | } 74 | } 75 | 76 | async getTransaction(transactionId: string): Promise { 77 | throw new Error('Not implemented.') 78 | } 79 | 80 | async setBlock(height: number, block: object, options: object = {}): Promise { 81 | this.blockCollection.push({ height, block }) 82 | } 83 | 84 | async pruneBlock(height: number, redundancySize: number): Promise { 85 | throw new Error('Not implemented.') 86 | } 87 | 88 | async analyzeBlocks(startHeight: number, endHeight: number): Promise { 89 | throw new Error('Not implemented.') 90 | } 91 | 92 | async getBlockMetaCount(): Promise { 93 | throw new Error('Not implemented.') 94 | } 95 | 96 | async getHighestBlockMetaHeight(): Promise { 97 | throw new Error('Not implemented.') 98 | } 99 | 100 | async getHighestBlockMeta(): Promise { 101 | throw new Error('Not implemented.') 102 | } 103 | 104 | async setBlockMeta(blockMeta: object): Promise { 105 | throw new Error('Not implemented.') 106 | } 107 | 108 | async setTransactionMeta(transactionMeta: object): Promise { 109 | throw new Error('Not implemented.') 110 | } 111 | 112 | async analyzeBlockMetas(startHeight: number, endHeight: number): Promise { 113 | throw new Error('Not implemented.') 114 | } 115 | 116 | async analyzeTransactionMetas(startHeight: number, endHeight: number): Promise { 117 | throw new Error('Not implemented.') 118 | } 119 | 120 | async removeBlockMetaByHeight(height: number): Promise { 121 | throw new Error('Not implemented.') 122 | } 123 | 124 | async countLegacyTransactionMeta(targetApiLevel: number): Promise { 125 | throw new Error('Not implemented.') 126 | } 127 | 128 | async pruneLegacyTransactionMeta(targetApiLevel: number): Promise { 129 | throw new Error('Not implemented.') 130 | } 131 | 132 | async close(): Promise { 133 | this.logger.debug('close triggered.') 134 | } 135 | 136 | private setReady() { 137 | this._isReady = true 138 | this.emit('ready') 139 | } 140 | 141 | private validateOptionalParameters() { 142 | // TODO 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /src/storages/mongodb/block-dao.ts: -------------------------------------------------------------------------------- 1 | import { Mongoose } from 'mongoose' 2 | import { blockSchema } from './schemas' 3 | import { MongodbUtils } from './utils' 4 | 5 | export class BlockDao { 6 | private model: any 7 | 8 | constructor(mongoose: Mongoose, collectionName: string) { 9 | this.model = this.getModel(mongoose, collectionName) 10 | } 11 | 12 | async countByHeight(height: number): Promise { 13 | return await this.model.countDocuments({ height }).exec() 14 | } 15 | 16 | async getHighestHeight(): Promise { 17 | const doc = await this.model 18 | .findOne({}, 'height') 19 | .sort({ height: -1 }) 20 | .exec() 21 | return doc.height 22 | } 23 | 24 | async getByHeight(height: number): Promise { 25 | /** 26 | * NOTE: 27 | * It is assumed that there may be multiple matches and will pick 'latest created' one as truth. 28 | */ 29 | return await this.model 30 | .findOne({ height }) 31 | .sort({ createdAt: -1 }) 32 | .exec() 33 | } 34 | 35 | async listByHeight(height: number): Promise { 36 | const result = await this.model 37 | .find({ height }) 38 | .sort({ createdAt: -1 }) 39 | .exec() 40 | if (!result) { 41 | return [] 42 | } 43 | // TODO: Verify if res is array 44 | return result 45 | } 46 | 47 | async getByTransactionId(transactionId: string): Promise { 48 | return await this.model 49 | .findOne({ 50 | 'payload.tx': { 51 | $elemMatch: { 52 | txid: transactionId, 53 | }, 54 | }, 55 | }) 56 | .exec() 57 | } 58 | 59 | async save(data: object): Promise { 60 | await this.model(data).save() 61 | } 62 | 63 | async deleteManyById(id: string): Promise { 64 | await this.model.deleteMany({ _id: id }).exec() 65 | } 66 | 67 | async analyze(startHeight: number, endHeight: number): Promise { 68 | /** 69 | * Example result: 70 | * [ 71 | * { _id: 1, count: 1 }, 72 | * { _id: 2, count: 4 }, 73 | * ... 74 | * ] 75 | */ 76 | const aggregatorOptions = [ 77 | { 78 | $group: { 79 | _id: '$height', 80 | count: { $sum: 1 }, 81 | }, 82 | }, 83 | { 84 | $match: { 85 | _id: { 86 | // This '_id' is now referring to $height as designated in $group 87 | $gte: startHeight, 88 | $lte: endHeight, 89 | }, 90 | }, 91 | }, 92 | ] 93 | return await this.model 94 | .aggregate(aggregatorOptions) 95 | .allowDiskUse(true) 96 | .exec() 97 | } 98 | 99 | async reviewIndex(key: string, keyObj: object): Promise { 100 | return await MongodbUtils.reviewIndex(this.model, key, keyObj) 101 | } 102 | 103 | private getModel(mongoose: Mongoose, collectionName: string) { 104 | const schema = blockSchema 105 | return mongoose.models[collectionName] || mongoose.model(collectionName, schema) 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/storages/mongodb/block-meta-dao.ts: -------------------------------------------------------------------------------- 1 | import { Mongoose } from 'mongoose' 2 | import { blockMetaSchema } from './schemas' 3 | import { MongodbUtils } from './utils' 4 | 5 | export class BlockMetaDao { 6 | private model: any 7 | 8 | constructor(mongoose: Mongoose, collectionName: string) { 9 | this.model = this.getModel(mongoose, collectionName) 10 | } 11 | 12 | async count(): Promise { 13 | return await this.model.countDocuments({}).exec() 14 | } 15 | 16 | async getHighest(): Promise { 17 | return await this.model 18 | .findOne() 19 | .sort({ height: -1 }) 20 | .exec() 21 | } 22 | 23 | async getHighestHeight(): Promise { 24 | // TODO: evaluate placement of business logic in DAO 25 | try { 26 | const doc: any = await this.getHighest() 27 | return doc.height 28 | } catch (err) { 29 | return 0 30 | } 31 | } 32 | 33 | async save(data: object): Promise { 34 | return await this.model(data).save() 35 | } 36 | 37 | async removeByHeight(height: number): Promise { 38 | return await this.model.deleteMany({ height }).exec() 39 | } 40 | 41 | async analyze(startHeight: number, endHeight: number): Promise { 42 | /** 43 | * Example Result: 44 | * [ 45 | * { _id: 5bff81ccbbd4fc5d6f3352d5, height: 95, apiLevel: 1 }, 46 | * { _id: 5bff81ccbbd4fc5d6f3352d9, height: 96, apiLevel: 1 }, 47 | * ... 48 | * ] 49 | */ 50 | return await this.model 51 | .find( 52 | { 53 | height: { 54 | $gte: startHeight, 55 | $lte: endHeight, 56 | }, 57 | }, 58 | 'height apiLevel' 59 | ) 60 | .exec() 61 | } 62 | 63 | async reviewIndex(key: string, keyObj: object): Promise { 64 | return await MongodbUtils.reviewIndex(this.model, key, keyObj) 65 | } 66 | 67 | private getModel(mongoose: Mongoose, collectionName: string) { 68 | const schema = blockMetaSchema 69 | return mongoose.models[collectionName] || mongoose.model(collectionName, schema) 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/storages/mongodb/schemas.ts: -------------------------------------------------------------------------------- 1 | import { Schema } from 'mongoose' 2 | 3 | export const blockSchema = new Schema( 4 | { 5 | height: Number, 6 | createdBy: String, 7 | source: String, 8 | userAgent: String, 9 | payload: { 10 | hash: String, 11 | size: Number, 12 | version: Number, 13 | previousblockhash: String, 14 | merkleroot: String, 15 | time: Number, 16 | index: { type: 'Number', required: true }, 17 | nonce: String, 18 | nextconsensus: String, 19 | script: { 20 | invocation: String, 21 | verification: String, 22 | }, 23 | tx: [], 24 | confirmations: Number, 25 | nextblockhash: String, 26 | }, 27 | }, 28 | { timestamps: true } 29 | ) 30 | 31 | export const blockMetaSchema = new Schema( 32 | { 33 | height: { type: 'Number', unique: true, required: true, dropDups: true }, 34 | time: Number, 35 | size: Number, 36 | generationTime: Number, 37 | transactionCount: Number, 38 | createdBy: String, 39 | apiLevel: Number, 40 | }, 41 | { timestamps: true } 42 | ) 43 | 44 | export const transactionMetaSchema = new Schema( 45 | { 46 | height: Number, 47 | time: Number, 48 | transactionId: { type: 'String', unique: true, required: true, dropDups: true }, 49 | type: String, 50 | size: Number, 51 | networkFee: Number, 52 | systemFee: Number, 53 | voutCount: Number, 54 | vinCount: Number, 55 | createdBy: String, 56 | apiLevel: Number, 57 | }, 58 | { timestamps: true } 59 | ) 60 | -------------------------------------------------------------------------------- /src/storages/mongodb/transaction-meta-dao.ts: -------------------------------------------------------------------------------- 1 | import { Mongoose } from 'mongoose' 2 | import { transactionMetaSchema } from './schemas' 3 | import { MongodbUtils } from './utils' 4 | 5 | export class TransactionMetaDao { 6 | private model: any 7 | 8 | constructor(mongoose: Mongoose, collectionName: string) { 9 | this.model = this.getModel(mongoose, collectionName) 10 | } 11 | 12 | async count(): Promise { 13 | return await this.model.countDocuments({}).exec() 14 | } 15 | 16 | async save(data: object): Promise { 17 | return await this.model(data).save() 18 | } 19 | 20 | async countByBelowApiLevel(apiLevel: number): Promise { 21 | return await this.model 22 | .countDocuments({ 23 | apiLevel: { $lt: apiLevel }, 24 | }) 25 | .exec() 26 | } 27 | 28 | async removeByBelowApiLevel(apiLevel: number): Promise { 29 | return await this.model 30 | .deleteMany({ 31 | apiLevel: { $lt: apiLevel }, 32 | }) 33 | .exec() 34 | } 35 | 36 | async analyze(startHeight: number, endHeight: number): Promise { 37 | /** 38 | * Example Result: 39 | * [ 40 | * { _id: 5bff81ccbbd4fc5d6f3352d5, height: 95, apiLevel: 1 }, 41 | * { _id: 5bff81ccbbd4fc5d6f3352d9, height: 96, apiLevel: 1 }, 42 | * ... 43 | * ] 44 | */ 45 | return await this.model 46 | .find( 47 | { 48 | height: { 49 | $gte: startHeight, 50 | $lte: endHeight, 51 | }, 52 | }, 53 | 'height apiLevel' 54 | ) 55 | .exec() 56 | } 57 | 58 | async reviewIndex(key: string, keyObj: object): Promise { 59 | return await MongodbUtils.reviewIndex(this.model, key, keyObj) 60 | } 61 | 62 | private getModel(mongoose: Mongoose, collectionName: string) { 63 | const schema = transactionMetaSchema 64 | return mongoose.models[collectionName] || mongoose.model(collectionName, schema) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/storages/mongodb/utils.ts: -------------------------------------------------------------------------------- 1 | import { includes } from 'lodash' 2 | 3 | export class MongodbUtils { 4 | static async reviewIndex(model: any, key: string, keyObj: object): Promise { 5 | const hasRequiredIndex = await MongodbUtils.hasIndex(model, key) 6 | if (hasRequiredIndex) { 7 | return 8 | } 9 | await MongodbUtils.createIndex(model, keyObj) 10 | } 11 | 12 | static async hasIndex(model: any, key: string): Promise { 13 | const indexes = await model.collection.getIndexes() 14 | const keys = Object.keys(indexes) 15 | const canFindIndex = includes(keys, key) 16 | return canFindIndex 17 | } 18 | 19 | static async createIndex(model: any, keyObj: object): Promise { 20 | await model.collection.createIndex(keyObj) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/validators/endpoint-validator.ts: -------------------------------------------------------------------------------- 1 | export class EndpointValidator { 2 | static validateArray(endpoints: object[]) { 3 | if (endpoints.length <= 0) { 4 | throw new Error(`'endpoints' must be an non empty array.`) 5 | } 6 | endpoints.forEach((ep: any) => { 7 | if (!ep.endpoint) { 8 | throw new Error(`item of 'endpoints' contain 'endpoint' property.`) 9 | } 10 | }) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/validators/mongodb-validator.ts: -------------------------------------------------------------------------------- 1 | import {} from 'lodash' 2 | 3 | export class MongodbValidator { 4 | static validateConnectionString(connectionString: string) { 5 | // TODO 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/validators/neo-validator.ts: -------------------------------------------------------------------------------- 1 | export class NeoValidator { 2 | static validateHeight(height: number) { 3 | if (height <= 0) { 4 | throw new Error(`'height' must be an integer 1 or above.`) 5 | } 6 | } 7 | 8 | static validateTransactionId(transactionId: string) { 9 | // TODO 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/validators/rpc-validator.ts: -------------------------------------------------------------------------------- 1 | import {} from 'lodash' 2 | 3 | export class RpcValidator { 4 | static validateUrl(url: string) { 5 | // TODO 6 | } 7 | 8 | static validateMethod(method: string) { 9 | // TODO 10 | } 11 | 12 | static validateId(id: number) { 13 | // TODO 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | var expect = require('chai').expect 3 | var Neo = require('../dist/neo').default 4 | 5 | describe('static version test', () => { 6 | it('should return 0.10.0', () => { 7 | var actual = Neo.VERSION 8 | expect(actual).to.equal('0.10.0') 9 | }) 10 | }) 11 | 12 | describe('instance version test', () => { 13 | it('should return 0.10.1', () => { 14 | var neo = new Neo() 15 | var actual = neo.VERSION 16 | expect(actual).to.equal('0.10.1') 17 | }) 18 | }) 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es6", 5 | "lib": [ "es6" ], 6 | "strict": true, 7 | "removeComments": true, 8 | "preserveConstEnums": true, 9 | "outDir": "dist", 10 | "declaration": true, 11 | "sourceMap": true, 12 | "esModuleInterop": true 13 | }, 14 | "include": [ 15 | "src/**/*.ts" 16 | ], 17 | "exclude": [ 18 | "node_modules" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint:recommended", 4 | "tslint-config-prettier" 5 | ], 6 | "rules": { 7 | "member-access": [true, "no-public"], 8 | "object-literal-sort-keys": false, 9 | "variable-name": [true, "allow-leading-underscore"], 10 | "interface-name": [true, "never-prefix"], 11 | "ordered-imports": false 12 | } 13 | } 14 | --------------------------------------------------------------------------------