├── .editorconfig ├── .firebaserc ├── .gitignore ├── LICENSE.md ├── README.md ├── angular.json ├── e2e ├── app.e2e-spec.ts ├── app.po.ts └── tsconfig.e2e.json ├── firebase.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── patch.js ├── protractor.conf.js ├── replace.build.js ├── server.js ├── src ├── app │ ├── account │ │ ├── account-routing.module.ts │ │ ├── account.module.ts │ │ └── account │ │ │ ├── account.component.html │ │ │ ├── account.component.scss │ │ │ ├── account.component.ts │ │ │ ├── actions │ │ │ ├── actions.component.html │ │ │ ├── actions.component.scss │ │ │ └── actions.component.ts │ │ │ ├── custom-tokens │ │ │ ├── custom-tokens.component.html │ │ │ ├── custom-tokens.component.scss │ │ │ └── custom-tokens.component.ts │ │ │ ├── information │ │ │ ├── information.component.html │ │ │ ├── information.component.scss │ │ │ └── information.component.ts │ │ │ ├── tables │ │ │ ├── tables.component.html │ │ │ ├── tables.component.scss │ │ │ └── tables.component.ts │ │ │ └── tokens │ │ │ ├── tokens.component.html │ │ │ ├── tokens.component.scss │ │ │ └── tokens.component.ts │ ├── app-routing.module.ts │ ├── app.component.html │ ├── app.component.scss │ ├── app.component.ts │ ├── app.module.ts │ ├── block │ │ ├── block-routing.module.ts │ │ ├── block.module.ts │ │ ├── block │ │ │ ├── block.component.html │ │ │ ├── block.component.scss │ │ │ ├── block.component.ts │ │ │ ├── information │ │ │ │ ├── information.component.html │ │ │ │ ├── information.component.scss │ │ │ │ └── information.component.ts │ │ │ └── transactions │ │ │ │ ├── transactions.component.html │ │ │ │ ├── transactions.component.scss │ │ │ │ └── transactions.component.ts │ │ └── blocks │ │ │ ├── blocks.component.html │ │ │ ├── blocks.component.scss │ │ │ └── blocks.component.ts │ ├── console │ │ ├── console-routing.module.ts │ │ ├── console.module.ts │ │ └── console │ │ │ ├── console.component.html │ │ │ ├── console.component.scss │ │ │ └── console.component.ts │ ├── dashboard │ │ ├── dashboard.module.ts │ │ ├── dashboard │ │ │ ├── blocks │ │ │ │ ├── blocks.component.html │ │ │ │ ├── blocks.component.scss │ │ │ │ └── blocks.component.ts │ │ │ ├── chain-status │ │ │ │ ├── chain-status.component.html │ │ │ │ ├── chain-status.component.scss │ │ │ │ └── chain-status.component.ts │ │ │ ├── dashboard.component.html │ │ │ ├── dashboard.component.scss │ │ │ ├── dashboard.component.ts │ │ │ ├── price │ │ │ │ ├── price.component.html │ │ │ │ ├── price.component.scss │ │ │ │ └── price.component.ts │ │ │ ├── transactions │ │ │ │ ├── transactions.component.html │ │ │ │ ├── transactions.component.scss │ │ │ │ └── transactions.component.ts │ │ │ └── trending │ │ │ │ ├── trending.component.html │ │ │ │ ├── trending.component.scss │ │ │ │ └── trending.component.ts │ │ ├── search │ │ │ ├── search.component.html │ │ │ ├── search.component.scss │ │ │ └── search.component.ts │ │ └── settings │ │ │ ├── settings.component.html │ │ │ ├── settings.component.scss │ │ │ └── settings.component.ts │ ├── models │ │ ├── Result.ts │ │ └── index.ts │ ├── producer │ │ ├── producer-routing.module.ts │ │ ├── producer.module.ts │ │ ├── producer │ │ │ ├── information │ │ │ │ ├── information.component.html │ │ │ │ ├── information.component.scss │ │ │ │ └── information.component.ts │ │ │ ├── nodes │ │ │ │ ├── nodes.component.html │ │ │ │ ├── nodes.component.scss │ │ │ │ └── nodes.component.ts │ │ │ ├── producer.component.html │ │ │ ├── producer.component.scss │ │ │ └── producer.component.ts │ │ ├── producers │ │ │ ├── producers.component.html │ │ │ ├── producers.component.scss │ │ │ └── producers.component.ts │ │ └── vote-progress-bar │ │ │ ├── vote-progress-bar.component.html │ │ │ ├── vote-progress-bar.component.scss │ │ │ └── vote-progress-bar.component.ts │ ├── services │ │ ├── app.service.ts │ │ ├── eos.service.ts │ │ ├── logger.service.ts │ │ └── scatter.service.ts │ ├── shared │ │ ├── error │ │ │ ├── error.component.html │ │ │ ├── error.component.scss │ │ │ └── error.component.ts │ │ ├── id64 │ │ │ ├── id64.component.html │ │ │ ├── id64.component.scss │ │ │ └── id64.component.ts │ │ ├── masterpage │ │ │ ├── header │ │ │ │ ├── header.component.html │ │ │ │ ├── header.component.scss │ │ │ │ └── header.component.ts │ │ │ ├── masterpage.component.html │ │ │ ├── masterpage.component.scss │ │ │ ├── masterpage.component.ts │ │ │ ├── search │ │ │ │ ├── search.component.html │ │ │ │ ├── search.component.scss │ │ │ │ └── search.component.ts │ │ │ └── sidenav │ │ │ │ ├── sidenav.component.html │ │ │ │ ├── sidenav.component.scss │ │ │ │ └── sidenav.component.ts │ │ ├── pipes │ │ │ └── tokb.pipes.ts │ │ ├── shared.module.ts │ │ ├── spinner │ │ │ ├── spinner.component.html │ │ │ ├── spinner.component.scss │ │ │ └── spinner.component.ts │ │ └── table │ │ │ ├── table.component.html │ │ │ ├── table.component.scss │ │ │ └── table.component.ts │ ├── support │ │ ├── support-routing.module.ts │ │ ├── support.component.1.html │ │ ├── support.component.html │ │ ├── support.component.scss │ │ ├── support.component.ts │ │ └── support.module.ts │ └── transaction │ │ ├── transaction-routing.module.ts │ │ ├── transaction.module.ts │ │ ├── transaction │ │ ├── actions │ │ │ ├── actions.component.html │ │ │ ├── actions.component.scss │ │ │ └── actions.component.ts │ │ ├── data │ │ │ ├── data.component.html │ │ │ ├── data.component.scss │ │ │ └── data.component.ts │ │ ├── information │ │ │ ├── information.component.html │ │ │ ├── information.component.scss │ │ │ └── information.component.ts │ │ ├── transaction.component.html │ │ ├── transaction.component.scss │ │ └── transaction.component.ts │ │ └── transactions │ │ ├── transactions.component.html │ │ ├── transactions.component.scss │ │ └── transactions.component.ts ├── assets │ ├── .gitkeep │ ├── fonts │ │ ├── flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2 │ │ └── fonts.css │ ├── i18n │ │ ├── de.json │ │ ├── dk.json │ │ ├── en.json │ │ ├── es.json │ │ ├── fr.json │ │ ├── hr.json │ │ ├── it.json │ │ ├── ko.json │ │ ├── pt.json │ │ ├── sl.json │ │ └── zh.json │ ├── logo.png │ └── nebula.jpg ├── environments │ ├── environment.prod.ts │ ├── environment.telos.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── material.scss ├── polyfills.ts ├── scripts.js ├── styles.scss ├── test.ts ├── themes.scss ├── tsconfig.app.json ├── tsconfig.spec.json └── typings.d.ts ├── tsconfig.json └── tslint.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.firebaserc: -------------------------------------------------------------------------------- 1 | { 2 | "projects": { 3 | "default": "eostrackerio" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | /build 4 | 5 | # compiled output 6 | /dist 7 | /tmp 8 | /out-tsc 9 | 10 | /_toremove 11 | 12 | # dependencies 13 | /node_modules 14 | 15 | # IDEs and editors 16 | /.idea 17 | .project 18 | .classpath 19 | .c9/ 20 | *.launch 21 | .settings/ 22 | *.sublime-workspace 23 | 24 | # IDE - VSCode 25 | .vscode/* 26 | !.vscode/settings.json 27 | !.vscode/tasks.json 28 | !.vscode/launch.json 29 | !.vscode/extensions.json 30 | 31 | # misc 32 | /.sass-cache 33 | /connect.lock 34 | /coverage 35 | /libpeerconnection.log 36 | npm-debug.log 37 | testem.log 38 | /typings 39 | 40 | # e2e 41 | /e2e/*.js 42 | /e2e/*.map 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 💎 EOS Tracker 2 | ======================== 3 | 4 | EOS Tracker is a Frontend based on Angular4 that connects to [EOS Tracker API](https://github.com/EOSEssentials/EOSTracker-API). 5 | 6 | 📌 Getting Started 7 | ------------ 8 | 9 | ```bash 10 | $ git clone git@github.com:EOSEssentials/EOSTracker.git 11 | $ cd EOSTracker 12 | $ npm install 13 | ``` 14 | 15 | 📌 Development server 16 | ------------ 17 | 18 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 19 | 20 | 21 | 📌 Code scaffolding 22 | ------------ 23 | 24 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. 25 | 26 | 📌 Build 27 | ------------ 28 | 29 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. 30 | 31 | 📌 Running unit tests 32 | ------------ 33 | 34 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 35 | 36 | 📌 Running end-to-end tests 37 | ------------ 38 | 39 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 40 | 41 | 📌 Further help 42 | ------------ 43 | 44 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 45 | oc/current/cookbook/configuration/web_server_configuration.html 46 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "eos-explorer": { 7 | "root": "", 8 | "sourceRoot": "src", 9 | "projectType": "application", 10 | "architect": { 11 | "build": { 12 | "builder": "@angular-devkit/build-angular:browser", 13 | "options": { 14 | "outputPath": "dist", 15 | "index": "src/index.html", 16 | "main": "src/main.ts", 17 | "tsConfig": "src/tsconfig.app.json", 18 | "polyfills": "src/polyfills.ts", 19 | "assets": [ 20 | "src/assets", 21 | "src/favicon.ico" 22 | ], 23 | "styles": [ 24 | "src/styles.scss", 25 | "src/themes.scss", 26 | "src/material.scss" 27 | ], 28 | "scripts": [ 29 | "src/scripts.js", 30 | "node_modules/confetti-js/dist/index.min.js" 31 | ] 32 | }, 33 | "configurations": { 34 | "production": { 35 | "optimization": true, 36 | "outputHashing": "all", 37 | "sourceMap": false, 38 | "extractCss": true, 39 | "namedChunks": false, 40 | "aot": true, 41 | "extractLicenses": true, 42 | "vendorChunk": false, 43 | "buildOptimizer": true, 44 | "fileReplacements": [ 45 | { 46 | "replace": "src/environments/environment.ts", 47 | "with": "src/environments/environment.prod.ts" 48 | } 49 | ] 50 | } 51 | } 52 | }, 53 | "serve": { 54 | "builder": "@angular-devkit/build-angular:dev-server", 55 | "options": { 56 | "browserTarget": "eos-explorer:build" 57 | }, 58 | "configurations": { 59 | "production": { 60 | "browserTarget": "eos-explorer:build:production" 61 | } 62 | } 63 | }, 64 | "extract-i18n": { 65 | "builder": "@angular-devkit/build-angular:extract-i18n", 66 | "options": { 67 | "browserTarget": "eos-explorer:build" 68 | } 69 | }, 70 | "test": { 71 | "builder": "@angular-devkit/build-angular:karma", 72 | "options": { 73 | "main": "src/test.ts", 74 | "karmaConfig": "./karma.conf.js", 75 | "polyfills": "src/polyfills.ts", 76 | "tsConfig": "src/tsconfig.spec.json", 77 | "scripts": [ 78 | "src/scripts.js" 79 | ], 80 | "styles": [ 81 | "src/styles.scss" 82 | ], 83 | "assets": [ 84 | "src/assets", 85 | "src/favicon.ico" 86 | ] 87 | } 88 | }, 89 | "lint": { 90 | "builder": "@angular-devkit/build-angular:tslint", 91 | "options": { 92 | "tsConfig": [ 93 | "src/tsconfig.app.json", 94 | "src/tsconfig.spec.json" 95 | ], 96 | "exclude": [ 97 | "**/node_modules/**" 98 | ] 99 | } 100 | } 101 | } 102 | }, 103 | "eos-explorer-e2e": { 104 | "root": "e2e/", 105 | "projectType": "application", 106 | "architect": { 107 | "e2e": { 108 | "builder": "@angular-devkit/build-angular:protractor", 109 | "options": { 110 | "protractorConfig": "./protractor.conf.js", 111 | "devServerTarget": "eos-explorer:serve" 112 | } 113 | }, 114 | "lint": { 115 | "builder": "@angular-devkit/build-angular:tslint", 116 | "options": { 117 | "tsConfig": [ 118 | "e2e/tsconfig.e2e.json" 119 | ], 120 | "exclude": [ 121 | "**/node_modules/**" 122 | ] 123 | } 124 | } 125 | } 126 | } 127 | }, 128 | "defaultProject": "eos-explorer", 129 | "schematics": { 130 | "@schematics/angular:component": { 131 | "prefix": "app", 132 | "styleext": "scss" 133 | }, 134 | "@schematics/angular:directive": { 135 | "prefix": "app" 136 | } 137 | } 138 | } -------------------------------------------------------------------------------- /e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | 3 | describe('eos-explorer App', () => { 4 | let page: AppPage; 5 | 6 | beforeEach(() => { 7 | page = new AppPage(); 8 | }); 9 | 10 | it('should display welcome message', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('Welcome to app!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "target": "es5", 8 | "types": [ 9 | "jasmine", 10 | "jasminewd2", 11 | "node" 12 | ] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /firebase.json: -------------------------------------------------------------------------------- 1 | { 2 | "hosting": { 3 | "public": "dist", 4 | "ignore": [ 5 | "firebase.json", 6 | "**/.*", 7 | "**/node_modules/**" 8 | ], 9 | "rewrites": [ 10 | { 11 | "source": "**", 12 | "destination": "/index.html" 13 | } 14 | ] 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, 'coverage'), reports: [ 'html', 'lcovonly' ], 20 | fixWebpackSourcePaths: true 21 | }, 22 | 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false 30 | }); 31 | }; 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "eos-explorer", 3 | "version": "1.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "node server.js", 8 | "dev": "ng serve", 9 | "build": "node replace.build.js && ng build --prod", 10 | "test": "ng test", 11 | "lint": "ng lint", 12 | "e2e": "ng e2e", 13 | "postinstall": "node replace.build.js && node patch.js && ng build --aot --prod" 14 | }, 15 | "private": true, 16 | "dependencies": { 17 | "@agm/core": "^1.0.0-beta.3", 18 | "@angular/animations": "^6.1.2", 19 | "@angular/cdk": "^6.4.3", 20 | "@angular/common": "^6.1.2", 21 | "@angular/compiler": "^6.1.2", 22 | "@angular/core": "^6.1.2", 23 | "@angular/flex-layout": "6.0.0-beta.17", 24 | "@angular/forms": "^6.1.2", 25 | "@angular/http": "^6.1.2", 26 | "@angular/material": "^6.4.3", 27 | "@angular/platform-browser": "^6.1.2", 28 | "@angular/platform-browser-dynamic": "^6.1.2", 29 | "@angular/router": "^6.1.2", 30 | "@ngx-translate/core": "^10.0.2", 31 | "@ngx-translate/http-loader": "^3.0.1", 32 | "@swimlane/ngx-charts": "^9.0.0", 33 | "angular2-counto": "^1.2.5", 34 | "angular2-prettyjson": "^2.0.6", 35 | "confetti-js": "0.0.11", 36 | "core-js": "^2.5.7", 37 | "eosjs": "^16.0.0", 38 | "express": "^4.16.3", 39 | "moment": "^2.22.2", 40 | "ngx-json-viewer": "^2.3.1", 41 | "ngx-moment": "^3.1.0", 42 | "ngx-webstorage": "^2.0.1", 43 | "normalize.css": "^8.0.0", 44 | "path": "^0.12.7", 45 | "rxjs": "^6.2.2", 46 | "zone.js": "^0.8.26" 47 | }, 48 | "devDependencies": { 49 | "@angular-devkit/build-angular": "^0.13.8", 50 | "@angular/cli": "^6.1.5", 51 | "@angular/compiler-cli": "^6.1.4", 52 | "@angular/language-service": "^6.1.4", 53 | "@types/google.analytics": "0.0.36", 54 | "@types/jasmine": "^2.8.8", 55 | "@types/jasminewd2": "~2.0.2", 56 | "@types/node": "^6.0.116", 57 | "codelyzer": "^4.4.4", 58 | "jasmine-core": "~2.8.0", 59 | "jasmine-spec-reporter": "~4.2.1", 60 | "karma": "^2.0.5", 61 | "karma-chrome-launcher": "~2.2.0", 62 | "karma-cli": "~1.0.1", 63 | "karma-coverage-istanbul-reporter": "^1.4.3", 64 | "karma-jasmine": "^1.1.2", 65 | "karma-jasmine-html-reporter": "^0.2.2", 66 | "protractor": "^5.4.0", 67 | "replace-in-file": "^3.4.4", 68 | "ts-node": "~4.1.0", 69 | "tslint": "~5.9.1", 70 | "typescript": "2.7.2" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /patch.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const f = 'node_modules/@angular-devkit/build-angular/src/angular-cli-files/models/webpack-configs/browser.js'; 3 | 4 | fs.readFile(f, 'utf8', function (err, data) { 5 | if (err) { 6 | return console.log(err); 7 | } 8 | var result = data.replace(/node: false/g, 'node: {crypto: true, stream: true}'); 9 | 10 | fs.writeFile(f, result, 'utf8', function (err) { 11 | if (err) return console.log(err); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | onPrepare() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 27 | } 28 | }; 29 | -------------------------------------------------------------------------------- /replace.build.js: -------------------------------------------------------------------------------- 1 | var replace = require('replace-in-file'); 2 | const options = { 3 | files: 'src/environments/environment.prod.ts', 4 | from: [ 5 | /{WALLET_URL}/g, 6 | /{VOTING_URL}/g, 7 | /{APP_NAME}/g, 8 | /{LOGO_URL}/g, 9 | /{BLOCKCHAIN_URL}/g, 10 | /{CHAIN_ID}/g, 11 | /{SHOW_ADS}/g, 12 | /{TOKENS_URL}/g, 13 | /{TICKER_URL}/g, 14 | /{TOKEN}/g 15 | ], 16 | to: [ 17 | process.env.WALLET_URL, 18 | process.env.VOTING_URL, 19 | process.env.APP_NAME, 20 | process.env.LOGO_URL, 21 | process.env.BLOCKCHAIN_URL, 22 | process.env.CHAIN_ID, 23 | process.env.SHOW_ADS, 24 | process.env.TOKENS_URL, 25 | process.env.TICKER_URL, 26 | process.env.TOKEN 27 | ], 28 | allowEmptyPaths: false 29 | }; 30 | 31 | replace.sync(options); 32 | -------------------------------------------------------------------------------- /server.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const path = require('path'); 3 | const app = express(); 4 | app.use(express.static(__dirname + '/dist')); 5 | app.get('*', function(req,res) { 6 | res.sendFile(path.join(__dirname+'/dist/index.html')); 7 | }); 8 | app.listen(process.env.PORT || 8080); -------------------------------------------------------------------------------- /src/app/account/account-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { AccountComponent } from './account/account.component'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: ':id', 9 | component: AccountComponent 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule] 16 | }) 17 | export class AccountRoutingModule { } 18 | -------------------------------------------------------------------------------- /src/app/account/account.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { AccountRoutingModule } from './account-routing.module'; 4 | import { MatDialogModule } from '@angular/material/dialog'; 5 | import { MatFormFieldModule } from '@angular/material/form-field'; 6 | import { MatInputModule } from '@angular/material/input'; 7 | import { NgxChartsModule } from '@swimlane/ngx-charts'; 8 | 9 | import { AccountComponent } from './account/account.component'; 10 | import { InformationComponent } from './account/information/information.component'; 11 | import { TablesComponent } from './account/tables/tables.component'; 12 | import { ActionsComponent } from './account/actions/actions.component'; 13 | import { TokensComponent } from './account/tokens/tokens.component'; 14 | import { CustomTokensComponent } from './account/custom-tokens/custom-tokens.component'; 15 | 16 | @NgModule({ 17 | imports: [ 18 | SharedModule, 19 | AccountRoutingModule, 20 | MatDialogModule, 21 | MatFormFieldModule, 22 | MatInputModule, 23 | NgxChartsModule 24 | ], 25 | declarations: [ 26 | AccountComponent, 27 | InformationComponent, 28 | TablesComponent, 29 | ActionsComponent, 30 | TokensComponent, 31 | CustomTokensComponent 32 | ], 33 | entryComponents: [ 34 | CustomTokensComponent 35 | ] 36 | }) 37 | export class AccountModule { } 38 | -------------------------------------------------------------------------------- /src/app/account/account/account.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Account' | translate }} {{name$ | async}} 4 |

5 |
6 | 7 | 8 | 9 | 10 | 11 | 18 | 19 | 20 | list 21 | {{ 'Actions' | translate }} 22 | 23 | 24 | 25 | 26 | 27 | code 28 | {{ 'BlockchainRawData' | translate }} 29 | 30 | 31 | 32 | 33 | 34 | code 35 | {{ 'Contract' | translate }} 36 | 37 | 38 |
39 | 40 |
41 | 42 | 43 | 44 |
45 |
46 | 55 |
56 |
57 | 58 | 59 | 60 |
61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/app/account/account/account.component.scss: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/account/account/account.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { EosService } from '../../services/eos.service'; 4 | import { AppService } from '../../services/app.service'; 5 | import { Result } from '../../models'; 6 | import { Observable } from 'rxjs'; 7 | import { map, switchMap, tap } from 'rxjs/operators'; 8 | 9 | @Component({ 10 | templateUrl: './account.component.html', 11 | styleUrls: ['./account.component.scss'] 12 | }) 13 | export class AccountComponent implements OnInit { 14 | 15 | name$: Observable; 16 | account$: Observable>; 17 | accountTokens$: Observable; 18 | accountActions$: Observable>; 19 | accountNewActions$: Observable>; 20 | accountAbi$: Observable>; 21 | 22 | constructor( 23 | private route: ActivatedRoute, 24 | private eosService: EosService, 25 | public app: AppService 26 | ) { } 27 | 28 | ngOnInit() { 29 | this.name$ = this.route.params.pipe( 30 | map(params => params.id) 31 | ); 32 | this.account$ = this.name$.pipe( 33 | switchMap(name => this.eosService.getAccountRaw(name)), 34 | tap(account => console.log('account', account)) 35 | ); 36 | this.accountTokens$ = this.name$.pipe( 37 | switchMap(name => this.eosService.getAccountTokens(name)) 38 | ); 39 | this.accountActions$ = this.name$.pipe( 40 | switchMap(name => this.eosService.getAccountActions(name)) 41 | ); 42 | this.accountAbi$ = this.name$.pipe( 43 | switchMap(name => this.eosService.getAbi(name)) 44 | ); 45 | } 46 | 47 | loadMore(sequence: number) { 48 | this.accountNewActions$ = this.name$.pipe( 49 | switchMap(name => this.eosService.getAccountActions(name, sequence)) 50 | ); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/app/account/account/actions/actions.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 20 | 21 | 22 | 23 | 26 | 27 | 28 | 29 | 34 | 35 | 36 | 37 | 40 | 41 | 42 | 43 | 46 | 47 |
{{ 'Action ID' | translate }} 10 | 18 | {{action.account_action_seq + 1}} 19 | {{ 'Block ID' | translate }} 24 | {{action.block_num}} 25 | {{ 'Transaction ID' | translate }} 30 | 31 | 32 | 33 | {{ 'Timestamp' | translate }} 38 | {{action.block_time | amFromUtc | date:'MMM d, y, h:mm:ss.SSS a'}} 39 | {{ 'Name' | translate }} 44 | {{action.action_trace.act.name}} 45 |
48 |
49 | 50 |
51 |
52 | 53 |

No Actions

54 |
55 |
56 | 57 | 58 | 59 |
60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/app/account/account/actions/actions.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | padding: 10px; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/account/account/actions/actions.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnChanges, Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-account-actions', 5 | templateUrl: './actions.component.html', 6 | styleUrls: ['./actions.component.scss'] 7 | }) 8 | export class ActionsComponent implements OnChanges { 9 | 10 | @Input() actions; 11 | @Input() newActions; 12 | @Output() onLoadMore = new EventEmitter(); 13 | actionsColumns = [ 14 | 'id', 15 | 'blockId', 16 | 'transactionId', 17 | 'timestamp', 18 | 'name' 19 | ]; 20 | accountActionSequence = 0; 21 | 22 | constructor() { } 23 | 24 | ngOnChanges() { 25 | if (this.newActions && !this.newActions.isError) { 26 | this.actions.value = this.actions.value.concat(this.newActions.value); 27 | this.newActions = null; 28 | } 29 | if (this.actions && !this.actions.isError && this.actions.value.length) { 30 | this.accountActionSequence = this.actions.value[this.actions.value.length - 1].account_action_seq; 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/app/account/account/custom-tokens/custom-tokens.component.html: -------------------------------------------------------------------------------- 1 |
2 |

Custom Tokens

3 | 6 |
7 | 8 |
9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 |
20 |
21 | Balance: {{token}} 22 |
23 |
24 |

25 | By default, we support the following tokens automatically. If the token you are looking for is not in this list, you need 26 | to manually enter the token account and symbol, so we can help you to check. 27 |

28 |
29 | 30 | 31 | 32 | {{token.name}} 33 | {{token.symbol}} 34 | 35 | 36 |
37 |
38 | -------------------------------------------------------------------------------- /src/app/account/account/custom-tokens/custom-tokens.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/account/account/custom-tokens/custom-tokens.component.scss -------------------------------------------------------------------------------- /src/app/account/account/custom-tokens/custom-tokens.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Inject } from '@angular/core'; 2 | import { FormGroup, FormControl } from '@angular/forms'; 3 | import { MAT_DIALOG_DATA } from '@angular/material'; 4 | import { AppService } from '../../../services/app.service'; 5 | import { EosService } from '../../../services/eos.service'; 6 | import { from } from 'rxjs'; 7 | import { filter, map } from 'rxjs/operators'; 8 | 9 | @Component({ 10 | selector: 'app-custom-tokens', 11 | templateUrl: './custom-tokens.component.html', 12 | styleUrls: ['./custom-tokens.component.scss'] 13 | }) 14 | export class CustomTokensComponent implements OnInit { 15 | 16 | tokenForm = new FormGroup({ 17 | account: new FormControl(''), 18 | symbol: new FormControl('') 19 | }); 20 | allTokens$; 21 | token$; 22 | 23 | constructor( 24 | @Inject(MAT_DIALOG_DATA) private data: any, 25 | private appService: AppService, 26 | private eosService: EosService 27 | ) { } 28 | 29 | ngOnInit() { 30 | this.allTokens$ = this.appService.getTokens(); 31 | } 32 | 33 | submit() { 34 | const token = this.tokenForm.value; 35 | this.token$ = from(this.eosService.eos.getCurrencyBalance(token.account, this.data.account, token.symbol)).pipe( 36 | filter((balance: string[]) => balance && balance.length > 0), 37 | map(balance => balance[0]) 38 | ); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/app/account/account/information/information.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | {{ 'Account Information' | translate }} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 20 | 21 | 22 | 23 | 24 | 30 | 31 | 32 | 39 | 40 | 41 | 42 | 50 | 51 | 52 | 53 | 61 | 62 | 63 | 64 | 74 | 75 |
{{ 'Account Name' | translate }}:{{account.account_name}}
{{ 'Created' | translate }}:{{account.created | amFromUtc | date:'medium'}}
{{ 'Balance' | translate }}:{{account.core_liquid_balance}}
{{ 'RAM' | translate }}: 33 |
34 | Staked: {{account.ram_quota * ramQuote.price | number:'1.0-4'}} EOS 35 |
Used: {{account.ram_usage | toKB | number:'1.0-2'}} KB 36 |
Max: {{account.ram_quota | toKB | number:'1.0-2'}} KB 37 |
38 |
{{ 'CPU' | translate }}: 43 |
44 | Staked: {{account.total_resources?.cpu_weight}} 45 |
Used: {{account.cpu_limit.used | number}} µs 46 |
Available: {{account.cpu_limit.available | number}} µs 47 |
Max: {{account.cpu_limit.max | number}} µs 48 |
49 |
{{ 'NET' | translate }}: 54 |
55 | Staked: {{account.total_resources?.net_weight}} 56 |
Used: {{(account.net_limit.used) | toKB | number:'1.0-2'}} KB 57 |
Available: {{(account.net_limit.available) | toKB | number:'1.0-2'}} KB 58 |
Max: {{(account.net_limit.max) | toKB | number:'1.0-2'}} KB 59 |
60 |
{{ 'Value' | translate }}: 65 |
66 | Balance: {{this.balance.liquid | number:'1.0-4'}} EOS 67 |
CPU: {{this.balance.cpu | number:'1.0-4'}} EOS 68 |
NET: {{this.balance.net | number:'1.0-4'}} EOS 69 |
RAM: {{this.balance.ram | number:'1.0-4'}} EOS 70 |
Total EOS: {{this.balance.total | number:'1.0-4'}} EOS 71 |
Total USD: {{this.balance.total * this.eosQuote.price | currency}} 72 |
73 |
76 |
77 |
78 |
79 | -------------------------------------------------------------------------------- /src/app/account/account/information/information.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/account/account/information/information.component.scss -------------------------------------------------------------------------------- /src/app/account/account/information/information.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnChanges, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-account-information', 5 | templateUrl: './information.component.html', 6 | styleUrls: ['./information.component.scss'] 7 | }) 8 | export class InformationComponent implements OnChanges { 9 | 10 | @Input() account; 11 | @Input() eosQuote; 12 | @Input() ramQuote; 13 | balance: { 14 | liquid: number; 15 | ram: number; 16 | cpu: number; 17 | net: number; 18 | total?: number; 19 | }; 20 | 21 | constructor() { } 22 | 23 | ngOnChanges() { 24 | if (this.account && this.eosQuote && this.ramQuote) { 25 | this.balance = { 26 | liquid: this.account.core_liquid_balance ? Number(this.account.core_liquid_balance.replace('EOS', '')) : 0, 27 | ram: this.account.ram_quota * this.ramQuote.price, 28 | cpu: this.account.cpu_weight / 10000, 29 | net: this.account.net_weight / 10000 30 | }; 31 | this.balance.total = this.balance.liquid + this.balance.ram + this.balance.cpu + this.balance.net; 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/app/account/account/tables/tables.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{ 'Table' | translate }} - {{table.name}} 5 | 6 |
7 | 8 |
9 |
10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/app/account/account/tables/tables.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | padding: 10px; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/account/account/tables/tables.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import { EosService } from '../../../services/eos.service'; 3 | import { Observable, combineLatest, from } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | 6 | @Component({ 7 | selector: 'app-account-tables', 8 | templateUrl: './tables.component.html', 9 | styleUrls: ['./tables.component.scss'] 10 | }) 11 | export class TablesComponent implements OnInit { 12 | 13 | @Input() account; 14 | accountTables$: Observable; 15 | 16 | constructor( 17 | private eosService: EosService 18 | ) { } 19 | 20 | ngOnInit() { 21 | if (this.account && this.account.abi && this.account.abi.tables) { 22 | const table$s: Observable[] = this.account.abi.tables.map(table => { 23 | return from( 24 | this.eosService.eos.getTableRows(true, this.account.name, this.account.name, table.name, table.key_names[0]) 25 | ).pipe( 26 | map(tableRows => ({ ...table, ...tableRows })) 27 | ); 28 | }); 29 | this.accountTables$ = combineLatest(table$s); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/app/account/account/tokens/tokens.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | {{ 'Account Tokens' | translate }} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 | 20 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 37 | 38 | 39 | 40 | 43 | 44 |
{{ 'Logo' | translate }} 15 | 16 | {{ 'Name' | translate }} 21 | {{token.name}} 22 | {{ 'Symbol' | translate }} 27 | {{token.symbol}} 28 | {{ 'Account' | translate }} 33 | 34 | {{token.account}} 35 | 36 | {{ 'Balance' | translate }} 41 | {{token.balance}} {{token.symbol}} 42 |
45 |
46 | 47 | 48 | 49 |
50 |
51 |
52 | -------------------------------------------------------------------------------- /src/app/account/account/tokens/tokens.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/account/account/tokens/tokens.component.scss -------------------------------------------------------------------------------- /src/app/account/account/tokens/tokens.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnChanges, Input } from '@angular/core'; 2 | import { MatDialog } from '@angular/material'; 3 | import { CustomTokensComponent } from '../custom-tokens/custom-tokens.component'; 4 | 5 | @Component({ 6 | selector: 'app-account-tokens', 7 | templateUrl: './tokens.component.html', 8 | styleUrls: ['./tokens.component.scss'] 9 | }) 10 | export class TokensComponent implements OnChanges { 11 | 12 | @Input() tokens; 13 | @Input() account; 14 | tokensColumns = [ 15 | 'logo', 16 | 'name', 17 | 'symbol', 18 | 'account', 19 | 'balance' 20 | ]; 21 | 22 | constructor( 23 | private matDialog: MatDialog 24 | ) { } 25 | 26 | ngOnChanges() { 27 | } 28 | 29 | add() { 30 | this.matDialog.open(CustomTokensComponent, { 31 | autoFocus: false, 32 | data: { account: this.account } 33 | }); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { DashboardModule } from './dashboard/dashboard.module'; 4 | 5 | import { MasterpageComponent } from './shared/masterpage/masterpage.component'; 6 | import { DashboardComponent } from './dashboard/dashboard/dashboard.component'; 7 | import { SettingsComponent } from './dashboard/settings/settings.component'; 8 | import { SearchComponent } from './dashboard/search/search.component'; 9 | 10 | const appRoutes: Routes = [ 11 | { 12 | path: '', 13 | component: MasterpageComponent, 14 | children: [ 15 | { path: '', pathMatch: 'full', component: DashboardComponent }, 16 | { path: 'search', component: SearchComponent }, 17 | { path: 'settings', component: SettingsComponent }, 18 | { path: 'accounts', loadChildren: './account/account.module#AccountModule' }, 19 | { path: 'blocks', loadChildren: './block/block.module#BlockModule' }, 20 | { path: 'producers', loadChildren: './producer/producer.module#ProducerModule' }, 21 | { path: 'transactions', loadChildren: './transaction/transaction.module#TransactionModule' }, 22 | { path: 'console', loadChildren: './console/console.module#ConsoleModule' }, 23 | { path: 'support', loadChildren: './support/support.module#SupportModule' } 24 | ] 25 | } 26 | ]; 27 | 28 | @NgModule({ 29 | imports: [ 30 | DashboardModule, 31 | RouterModule.forRoot(appRoutes) 32 | ], 33 | exports: [ 34 | RouterModule 35 | ] 36 | }) 37 | export class AppRoutingModule { } 38 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/app.component.scss -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import {Component} from '@angular/core'; 2 | import {NavigationEnd, Router} from '@angular/router'; 3 | import {TranslateService} from '@ngx-translate/core'; 4 | import {LocalStorage} from 'ngx-webstorage'; 5 | 6 | declare let ga: Function; 7 | 8 | @Component({ 9 | selector: 'app-root', 10 | templateUrl: './app.component.html', 11 | styleUrls: ['./app.component.scss'] 12 | }) 13 | 14 | export class AppComponent { 15 | title = 'EOS Tracker | EosTracker.io'; 16 | @LocalStorage() 17 | language: any; 18 | 19 | constructor(public router: Router, private translate: TranslateService) { 20 | translate.setDefaultLang('en'); 21 | if (!this.language) { 22 | let browserLanguage = ((window).navigator) ? ((window).navigator.userLanguage || (window).navigator.language) : 'en'; 23 | this.language = browserLanguage.substring(0, 2); 24 | } 25 | 26 | translate.use(this.language); 27 | 28 | this.router.events.subscribe(event => { 29 | if (event instanceof NavigationEnd && typeof ga === "function") { 30 | ga('set', 'page', event.urlAfterRedirects); 31 | ga('send', 'pageview'); 32 | } 33 | }); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import { NgModule } from '@angular/core'; 4 | import { SharedModule } from './shared/shared.module'; 5 | import { AppRoutingModule } from './app-routing.module'; 6 | import { AppComponent } from './app.component'; 7 | import { HttpClient, HttpClientModule } from '@angular/common/http'; 8 | import { SafeJsonPipe } from 'angular2-prettyjson'; 9 | import { JsonPipe } from '@angular/common'; 10 | import { EosService } from './services/eos.service'; 11 | import { TranslateLoader, TranslateModule } from '@ngx-translate/core'; 12 | import { TranslateHttpLoader } from '@ngx-translate/http-loader'; 13 | import { Ng2Webstorage } from 'ngx-webstorage'; 14 | import { ScatterService } from './services/scatter.service'; 15 | import { AppService } from './services/app.service'; 16 | import { LoggerService } from './services/logger.service'; 17 | 18 | export function HttpLoaderFactory(http: HttpClient) { 19 | return new TranslateHttpLoader(http); 20 | } 21 | 22 | @NgModule({ 23 | declarations: [ 24 | AppComponent 25 | ], 26 | imports: [ 27 | BrowserAnimationsModule, 28 | BrowserModule, 29 | Ng2Webstorage, 30 | HttpClientModule, 31 | TranslateModule.forRoot({ 32 | loader: { 33 | provide: TranslateLoader, 34 | useFactory: HttpLoaderFactory, 35 | deps: [HttpClient] 36 | } 37 | }), 38 | SharedModule, 39 | AppRoutingModule 40 | ], 41 | providers: [ 42 | EosService, 43 | ScatterService, 44 | AppService, 45 | LoggerService, 46 | { provide: JsonPipe, useClass: SafeJsonPipe } 47 | ], 48 | bootstrap: [AppComponent] 49 | }) 50 | export class AppModule { 51 | } 52 | -------------------------------------------------------------------------------- /src/app/block/block-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { BlocksComponent } from './blocks/blocks.component'; 5 | import { BlockComponent } from './block/block.component'; 6 | 7 | const routes: Routes = [ 8 | { 9 | path: '', 10 | pathMatch: 'full', 11 | component: BlocksComponent 12 | }, 13 | { 14 | path: ':id', 15 | component: BlockComponent 16 | }, 17 | { 18 | path: ':id/transactions', 19 | component: BlockComponent 20 | } 21 | ]; 22 | 23 | @NgModule({ 24 | imports: [RouterModule.forChild(routes)], 25 | exports: [RouterModule] 26 | }) 27 | export class BlockRoutingModule { } 28 | -------------------------------------------------------------------------------- /src/app/block/block.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { BlockRoutingModule } from './block-routing.module'; 4 | import { MatPaginatorModule } from '@angular/material/paginator'; 5 | 6 | import { BlocksComponent } from './blocks/blocks.component'; 7 | import { BlockComponent } from './block/block.component'; 8 | import { InformationComponent } from './block/information/information.component'; 9 | import { TransactionsComponent } from './block/transactions/transactions.component'; 10 | 11 | @NgModule({ 12 | imports: [ 13 | SharedModule, 14 | BlockRoutingModule, 15 | MatPaginatorModule 16 | ], 17 | declarations: [ 18 | BlocksComponent, 19 | BlockComponent, 20 | InformationComponent, 21 | TransactionsComponent 22 | ] 23 | }) 24 | export class BlockModule { } 25 | -------------------------------------------------------------------------------- /src/app/block/block/block.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Block' | translate }} #{{id$ | async}} 4 |

5 |
6 | 7 | 8 | 9 | 10 | info 11 | {{ 'BlockInformation' | translate }} 12 | 13 | 14 | 15 | 16 | 17 | code 18 | {{ 'BlockchainRawData' | translate }} 19 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/app/block/block/block.component.scss: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/block/block/block.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { EosService } from '../../services/eos.service'; 4 | import { Result } from '../../models'; 5 | import { Observable } from 'rxjs'; 6 | import { switchMap, map } from 'rxjs/operators'; 7 | 8 | @Component({ 9 | templateUrl: './block.component.html', 10 | styleUrls: ['./block.component.scss'] 11 | }) 12 | export class BlockComponent implements OnInit { 13 | 14 | id$: Observable; 15 | block$: Observable>; 16 | 17 | constructor( 18 | private route: ActivatedRoute, 19 | private eosService: EosService 20 | ) { } 21 | 22 | ngOnInit() { 23 | this.id$ = this.route.params.pipe( 24 | map(params => +params.id) 25 | ); 26 | this.block$ = this.id$.pipe( 27 | switchMap(id => this.eosService.getBlockRaw(id)) 28 | ); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/app/block/block/information/information.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
{{ 'Block Number' | translate }}:{{block.block_num}}
{{ 'Block Producer' | translate }}: 12 | {{block.producer}} 13 |
{{ 'Timestamp' | translate }}:{{block.timestamp | amFromUtc | date:'MMM d, y, h:mm:ss.SSS a'}}
{{ 'Block ID' | translate }}:{{block.id}}
{{ 'Previous Block ID' | translate }}: 26 | {{block.previous}} 27 | {{block.previous}} 28 |
{{ 'Transaction Merkle Root' | translate }}:{{block.transaction_mroot}}
{{ 'Action Merkle Root' | translate }}:{{block.action_mroot}}
{{ 'Number of Transactions' | translate }}:{{block.transactions.length}}
43 |
44 |
45 |
46 | 47 |
48 |
49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/app/block/block/information/information.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/block/block/information/information.component.scss -------------------------------------------------------------------------------- /src/app/block/block/information/information.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-block-information', 5 | templateUrl: './information.component.html', 6 | styleUrls: ['./information.component.scss'] 7 | }) 8 | export class InformationComponent implements OnInit { 9 | 10 | @Input() block; 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/block/block/transactions/transactions.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 36 | 37 | 38 | 39 | 42 | 43 |
{{ 'Index' | translate }} 8 | {{i + 1}} 9 | {{ 'Transaction ID' | translate }} 14 | 15 | 16 | 17 | {{ 'Status' | translate }} 22 | {{transaction.status}} 23 | {{ 'CPU Usage' | translate }} 28 | {{transaction.cpu_usage_us | number }} µs 29 | {{ 'NET Usage' | translate }} 34 | {{transaction.net_usage_words | toKB | number:'1.0-3'}} KB 35 | {{ 'Actions' | translate }} 40 | {{transaction.trx.transaction?.actions.length || 0}} 41 |
44 |
45 | -------------------------------------------------------------------------------- /src/app/block/block/transactions/transactions.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/block/block/transactions/transactions.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-block-transactions', 5 | templateUrl: './transactions.component.html', 6 | styleUrls: ['./transactions.component.scss'] 7 | }) 8 | export class TransactionsComponent implements OnInit { 9 | 10 | @Input() block; 11 | transactionsColumns = [ 12 | 'index', 13 | 'id', 14 | 'status', 15 | 'cpu', 16 | 'net', 17 | 'actions' 18 | ]; 19 | 20 | constructor() { } 21 | 22 | ngOnInit() { 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/app/block/blocks/blocks.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Blocks' | translate }} 4 |

5 |
6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 36 | 37 |
{{ 'Block Number' | translate }} 16 | {{block.block_num}} 17 | {{ 'Timestamp' | translate }} 22 | {{block.timestamp | amFromUtc | date:'MMM d, y, h:mm:ss.SSS a'}} 23 | {{ 'Producer' | translate }} 28 | {{block.producer}} 29 | {{ 'Transactions' | translate }} 34 | {{block.transactions.length}} 35 |
38 | 39 |
40 | 41 | 42 | 43 |
44 | -------------------------------------------------------------------------------- /src/app/block/blocks/blocks.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/block/blocks/blocks.component.scss -------------------------------------------------------------------------------- /src/app/block/blocks/blocks.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 3 | import { Observable, of } from 'rxjs'; 4 | import { map, tap } from 'rxjs/operators'; 5 | import { AppService } from '../../services/app.service'; 6 | 7 | @Component({ 8 | templateUrl: './blocks.component.html', 9 | styleUrls: ['./blocks.component.scss'] 10 | }) 11 | export class BlocksComponent implements OnInit { 12 | 13 | columnHeaders$: Observable = of(BLOCK_COLUMNS); 14 | blocks$: Observable; 15 | pageIndex = 0; 16 | pageSize = 10; 17 | total = 0; 18 | 19 | constructor( 20 | private breakpointObserver: BreakpointObserver, 21 | private appService: AppService 22 | ) { } 23 | 24 | ngOnInit() { 25 | this.columnHeaders$ = this.breakpointObserver.observe(Breakpoints.XSmall).pipe( 26 | map(result => result.matches ? BLOCK_COLUMNS.filter(c => c !== 'timestamp') : BLOCK_COLUMNS) 27 | ); 28 | this.blocks$ = this.appService.getBlocks(this.pageIndex, this.pageSize).pipe( 29 | tap(blocks => { 30 | this.total = blocks[0].block_num; 31 | }) 32 | ); 33 | } 34 | 35 | onPaging(pageEvent) { 36 | this.pageIndex = pageEvent.pageIndex; 37 | this.blocks$ = this.appService.getBlocks(pageEvent.length - pageEvent.pageSize * pageEvent.pageIndex); 38 | } 39 | 40 | } 41 | 42 | export const BLOCK_COLUMNS = [ 43 | 'block_num', 44 | 'timestamp', 45 | 'producer', 46 | 'transactions' 47 | ]; 48 | -------------------------------------------------------------------------------- /src/app/console/console-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { ConsoleComponent } from './console/console.component'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | pathMatch: 'full', 10 | component: ConsoleComponent 11 | } 12 | ]; 13 | 14 | @NgModule({ 15 | imports: [RouterModule.forChild(routes)], 16 | exports: [RouterModule] 17 | }) 18 | export class ConsoleRoutingModule { } 19 | -------------------------------------------------------------------------------- /src/app/console/console.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { ConsoleRoutingModule } from './console-routing.module'; 4 | 5 | import { ConsoleComponent } from './console/console.component'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | SharedModule, 10 | ConsoleRoutingModule 11 | ], 12 | declarations: [ 13 | ConsoleComponent 14 | ] 15 | }) 16 | export class ConsoleModule { } 17 | -------------------------------------------------------------------------------- /src/app/console/console/console.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Console' | translate }} 4 |

5 | 6 | 7 | {{apiEndpoint}} 8 | 9 |
10 |
11 |

CHAIN

12 | 13 | 14 | 15 | 16 | get_info 17 | 18 | 19 | Returns an object containing various details about the blockchain. 20 | 21 | 22 | 23 | Body: 24 |
{{'{}'}}
25 |
26 | 27 | 28 | 29 |
30 | 31 | 32 | 33 | get_block 34 | 35 | 36 | Returns an object containing various details about a specific block on the blockchain. 37 | 38 | 39 | 40 | Body: 41 |
block_num_or_id (string)
42 |
43 | 44 | 45 | 46 |
47 |
48 |
49 | 50 |
51 |
52 | -------------------------------------------------------------------------------- /src/app/console/console/console.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/console/console/console.component.scss -------------------------------------------------------------------------------- /src/app/console/console/console.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { from } from 'rxjs'; 3 | import { EosService } from '../../services/eos.service'; 4 | 5 | @Component({ 6 | selector: 'app-console', 7 | templateUrl: './console.component.html', 8 | styleUrls: ['./console.component.scss'] 9 | }) 10 | export class ConsoleComponent implements OnInit { 11 | 12 | apiEndpoint$; 13 | result$; 14 | 15 | constructor( 16 | private eosService: EosService 17 | ) { } 18 | 19 | ngOnInit() { 20 | this.apiEndpoint$ = this.eosService.apiEndpoint$; 21 | } 22 | 23 | getInfo() { 24 | this.result$ = from(this.eosService.eos.getInfo({})); 25 | } 26 | 27 | getBlock(block_num_or_id: number) { 28 | this.result$ = from(this.eosService.eos.getBlock(block_num_or_id)); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { MatFormFieldModule } from '@angular/material/form-field'; 4 | import { MatSelectModule } from '@angular/material/select'; 5 | 6 | import { DashboardComponent } from './dashboard/dashboard.component'; 7 | import { SettingsComponent } from './settings/settings.component'; 8 | import { SearchComponent } from './search/search.component'; 9 | import { BlocksComponent } from './dashboard/blocks/blocks.component'; 10 | import { TransactionsComponent } from './dashboard/transactions/transactions.component'; 11 | import { ChainStatusComponent } from './dashboard/chain-status/chain-status.component'; 12 | import { PriceComponent } from './dashboard/price/price.component'; 13 | import { TrendingComponent } from './dashboard/trending/trending.component'; 14 | 15 | @NgModule({ 16 | imports: [ 17 | SharedModule, 18 | MatFormFieldModule, 19 | MatSelectModule 20 | ], 21 | declarations: [ 22 | DashboardComponent, 23 | SettingsComponent, 24 | SearchComponent, 25 | BlocksComponent, 26 | TransactionsComponent, 27 | ChainStatusComponent, 28 | PriceComponent, 29 | TrendingComponent 30 | ] 31 | }) 32 | export class DashboardModule { } 33 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/blocks/blocks.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | {{ 'Recent Blocks' | translate }} 4 |

5 | {{ 'ViewAll' | translate }} 6 |
7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 18 | 19 | 20 | 21 | 24 | 25 | 26 | 27 | 30 | 31 | 32 | 33 | 36 | 37 |
{{ 'Block Number' | translate }} 16 | {{block.block_num}} 17 | {{ 'Timestamp' | translate }} 22 | {{block.timestamp | amFromUtc | amTimeAgo}} 23 | {{ 'Producer' | translate }} 28 | {{block.producer}} 29 | {{ 'Transactions' | translate }} 34 | {{block.transactions.length}} 35 |
38 |
39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/blocks/blocks.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/blocks/blocks.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 3 | import { AppService } from '../../../services/app.service'; 4 | import { Observable, of } from 'rxjs'; 5 | import { map } from 'rxjs/operators'; 6 | 7 | @Component({ 8 | selector: 'app-dashboard-blocks', 9 | templateUrl: './blocks.component.html', 10 | styleUrls: ['./blocks.component.scss'] 11 | }) 12 | export class BlocksComponent implements OnInit { 13 | 14 | blocks$: Observable; 15 | blocksColumns$ = of(BLOCKS_COLUMNS); 16 | 17 | constructor( 18 | private breakpointObserver: BreakpointObserver, 19 | private appService: AppService 20 | ) { } 21 | 22 | ngOnInit() { 23 | this.blocks$ = this.appService.recentBlocks$; 24 | this.blocksColumns$ = this.breakpointObserver.observe(Breakpoints.XSmall).pipe( 25 | map(result => result.matches ? BLOCKS_COLUMNS.filter(c => c !== 'timestamp') : BLOCKS_COLUMNS) 26 | ); 27 | } 28 | 29 | } 30 | 31 | export const BLOCKS_COLUMNS = [ 32 | 'block_num', 33 | 'timestamp', 34 | 'producer', 35 | 'transactions' 36 | ]; 37 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/chain-status/chain-status.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | network_check 4 | {{ 'Network Info' | translate }} 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 | 31 | 32 | 33 | 34 |
{{ 'Server Version' | translate }}:{{status.server_version_string}}
{{ 'Chain ID' | translate }}:{{status.chain_id}}
{{ 'Head Block Timestamp' | translate }}:{{status.head_block_time | amFromUtc | date:'MMM d, y, h:mm:ss.SSS a'}}
{{ 'Head Block #' | translate }}:{{status.head_block_num}}
{{ 'Head Block Producer' | translate }}: 27 | {{status.head_block_producer}} 28 |
{{ 'Last Irreversible Block #' | translate }}:{{status.last_irreversible_block_num}}
35 |
36 |
37 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/chain-status/chain-status.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | .mat-card { 6 | height: calc(100% - 48px); 7 | } 8 | 9 | .mat-card-title .mat-icon { 10 | font-size: 30px; 11 | width: 30px; 12 | height: 30px; 13 | margin-right: 10px; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/chain-status/chain-status.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AppService } from '../../../services/app.service'; 3 | 4 | @Component({ 5 | selector: 'app-dashboard-chain-status', 6 | templateUrl: './chain-status.component.html', 7 | styleUrls: ['./chain-status.component.scss'] 8 | }) 9 | export class ChainStatusComponent implements OnInit { 10 | 11 | status$; 12 | 13 | constructor( 14 | private appService: AppService 15 | ) { } 16 | 17 | ngOnInit() { 18 | this.status$ = this.appService.info$; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/dashboard.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Dashboard' | translate }} 4 |

5 |
6 |
7 | 8 |
9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 |
17 |
18 | 19 |
20 |
21 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/dashboard.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/dashboard/dashboard/dashboard.component.scss -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/dashboard.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { AppService } from '../../services/app.service'; 3 | import { Observable } from 'rxjs'; 4 | import {environment} from '../../../environments/environment'; 5 | 6 | @Component({ 7 | templateUrl: './dashboard.component.html', 8 | styleUrls: ['./dashboard.component.scss'] 9 | }) 10 | export class DashboardComponent implements OnInit { 11 | 12 | eosQuote$: Observable; 13 | showAds = environment.showAds; 14 | 15 | constructor( 16 | private appService: AppService 17 | ) { } 18 | 19 | ngOnInit() { 20 | this.eosQuote$ = this.appService.eosQuote$; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/price/price.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | attach_money 4 | Price Info 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 28 | 29 | 30 | 31 | 35 | 36 | 37 | 38 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 |
Price{{usd.price | currency:'USD'}} USD
Volume 24h{{usd.volume_24h / 1000000 | currency:'USD':'symbol':'1.0-0'}}M USD
Market Cap{{usd.market_cap/ 1000000000 | currency:'USD':'symbol'}}B USD
% Change 1h 25 | {{usd.percent_change_1h / 100 | percent:'1.2'}} 26 | 27 |
% Change 24h 32 | {{usd.percent_change_24h / 100 | percent:'1.2'}} 33 | 34 |
% Change 7d 39 | {{usd.percent_change_7d / 100 | percent:'1.2'}} 40 | 41 |
Circulating Supply{{price.circulating_supply | number}} {{token}}
Total Supply{{price.total_supply | number}} {{token}}
53 |
54 |
55 |
56 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/price/price.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | .mat-card { 6 | height: calc(100% - 48px); 7 | } 8 | 9 | .mat-card-title .mat-icon { 10 | font-size: 30px; 11 | width: 30px; 12 | height: 30px; 13 | margin-right: 10px; 14 | } 15 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/price/price.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import {environment} from '../../../../environments/environment'; 3 | 4 | @Component({ 5 | selector: 'app-dashboard-price', 6 | templateUrl: './price.component.html', 7 | styleUrls: ['./price.component.scss'] 8 | }) 9 | export class PriceComponent implements OnInit { 10 | 11 | @Input() price: any; 12 | token = environment.token; 13 | 14 | constructor() { } 15 | 16 | ngOnInit() { 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/transactions/transactions.component.html: -------------------------------------------------------------------------------- 1 |
2 |

3 | {{ 'Recent Transactions' | translate }} 4 |

5 | {{ 'ViewAll' | translate }} 6 |
7 |
8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 21 | 22 | 23 | 24 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 39 | 40 | 41 | 42 | 45 | 46 |
{{ 'Transaction ID' | translate }} 17 | 18 | 19 | 20 | {{ 'Block Number' | translate }} 25 | {{transaction.block_num}} 26 | {{ 'CPU Usage' | translate }} 31 | {{transaction.cpu_usage_us | number }} µs 32 | {{ 'NET Usage' | translate }} 37 | {{transaction.net_usage_words | toKB | number:'1.0-3'}} KB 38 | {{ 'Actions' | translate }} 43 | {{transaction.trx.transaction?.actions?.length || 0}} 44 |
47 |
48 |
49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/transactions/transactions.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/transactions/transactions.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 3 | import { Observable, of } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | import { AppService } from '../../../services/app.service'; 6 | 7 | @Component({ 8 | selector: 'app-dashboard-transactions', 9 | templateUrl: './transactions.component.html', 10 | styleUrls: ['./transactions.component.scss'] 11 | }) 12 | export class TransactionsComponent implements OnInit { 13 | 14 | columnHeaders$: Observable = of(DEFAULT_HEADERS); 15 | transactions$; 16 | 17 | constructor( 18 | private breakpointObserver: BreakpointObserver, 19 | private appService: AppService 20 | ) { } 21 | 22 | ngOnInit() { 23 | this.columnHeaders$ = this.breakpointObserver.observe(Breakpoints.XSmall).pipe( 24 | map(result => result.matches ? XSMALL_HEADERS : DEFAULT_HEADERS) 25 | ); 26 | this.transactions$ = this.appService.recentTransactions$.pipe( 27 | map(transactions => transactions.slice(0, 50)) 28 | ); 29 | } 30 | 31 | } 32 | 33 | const DEFAULT_HEADERS = [ 34 | 'id', 35 | 'block_num', 36 | 'cpu', 37 | 'net', 38 | 'actions' 39 | ]; 40 | 41 | const XSMALL_HEADERS = [ 42 | 'id', 43 | 'block_num', 44 | 'actions' 45 | ]; 46 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/trending/trending.component.html: -------------------------------------------------------------------------------- 1 | 2 | trending_up 3 | 4 | 5 | trending_flat 6 | 7 | 8 | trending_down 9 | 10 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/trending/trending.component.scss: -------------------------------------------------------------------------------- 1 | .mat-icon { 2 | vertical-align: middle; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/dashboard/dashboard/trending/trending.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnChanges, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-price-trending', 5 | templateUrl: './trending.component.html', 6 | styleUrls: ['./trending.component.scss'] 7 | }) 8 | export class TrendingComponent implements OnChanges { 9 | 10 | @Input() percentage: number; 11 | 12 | constructor() { } 13 | 14 | ngOnChanges() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/dashboard/search/search.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Search' | translate }} "{{query$ | async}}" 4 |

5 |
6 |
7 |

No Result Found!

8 |

Here are the supported search queries.

9 |
    10 |
  • Block Number (e.g., 12345)
  • 11 |
  • Block ID (e.g., hash string of 64 characters)
  • 12 |
  • Transaction ID (e.g., hash string of 64 characters)
  • 13 |
  • Account Name (e.g., eosio)
  • 14 |
15 |
16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/app/dashboard/search/search.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/dashboard/search/search.component.scss -------------------------------------------------------------------------------- /src/app/dashboard/search/search.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { Observable, of, empty } from 'rxjs'; 4 | import { map, tap, switchMap, catchError } from 'rxjs/operators'; 5 | import { EosService } from '../../services/eos.service'; 6 | 7 | @Component({ 8 | selector: 'app-search', 9 | templateUrl: './search.component.html', 10 | styleUrls: ['./search.component.scss'] 11 | }) 12 | export class SearchComponent implements OnInit { 13 | 14 | query$: Observable; 15 | result$: Observable; 16 | 17 | constructor( 18 | private route: ActivatedRoute, 19 | private router: Router, 20 | private eosService: EosService 21 | ) { } 22 | 23 | ngOnInit() { 24 | this.query$ = this.route.queryParams.pipe( 25 | map(queryParams => queryParams.q) 26 | ); 27 | this.result$ = this.query$.pipe( 28 | switchMap(query => this.tryBlockNumber(query)), 29 | switchMap(query => this.tryTransaction(query)), 30 | switchMap(query => this.tryBlockId(query)), 31 | switchMap(query => this.tryAccount(query)), 32 | tap(query => console.log('no result', query)) 33 | ); 34 | } 35 | 36 | private tryBlockNumber(query: string): Observable { 37 | const blockNumber = Number(query); 38 | if (!isNaN(blockNumber)) { 39 | return this.eosService.getDeferBlock(blockNumber).pipe( 40 | catchError(() => of(null)), 41 | switchMap(data => { 42 | if (data) { 43 | this.router.navigate(['/blocks', blockNumber], { replaceUrl: true }); 44 | return empty(); 45 | } 46 | return of(query); 47 | }) 48 | ); 49 | } 50 | return of(query); 51 | } 52 | 53 | private tryTransaction(query: string): Observable { 54 | if (query.length === 64) { 55 | return this.eosService.getDeferTransaction(query).pipe( 56 | catchError(() => of(null)), 57 | switchMap(transaction => { 58 | if (transaction) { 59 | this.router.navigate(['/transactions', transaction.block_num, transaction.id], { replaceUrl: true }); 60 | return empty(); 61 | } 62 | return of(query); 63 | }) 64 | ); 65 | } 66 | return of(query); 67 | } 68 | 69 | private tryBlockId(query: string): Observable { 70 | if (query.length === 64) { 71 | return this.eosService.getDeferBlock(query).pipe( 72 | catchError(() => of(null)), 73 | switchMap(block => { 74 | if (block) { 75 | this.router.navigate(['/blocks', block.block_num], { replaceUrl: true }); 76 | return empty(); 77 | } 78 | return of(query); 79 | }) 80 | ); 81 | } 82 | return of(query); 83 | } 84 | 85 | private tryAccount(query: string): Observable { 86 | if (query.length <= 12) { 87 | return this.eosService.getDeferAccount(query).pipe( 88 | catchError(() => of(null)), 89 | switchMap(account => { 90 | if (account) { 91 | this.router.navigate(['/accounts', account.account_name], { replaceUrl: true }); 92 | return empty(); 93 | } 94 | return of(query); 95 | }) 96 | ); 97 | } 98 | return of(query); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /src/app/dashboard/settings/settings.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Settings' | translate }} 4 |

5 |
6 |
7 | 8 | 9 | 10 | {{language.name}} 11 | 12 | 13 | 14 |
15 |
16 | 17 | 18 | 19 | {{api.name}} 20 | 21 | 22 | 23 |
24 | -------------------------------------------------------------------------------- /src/app/dashboard/settings/settings.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/dashboard/settings/settings.component.scss -------------------------------------------------------------------------------- /src/app/dashboard/settings/settings.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormControl } from '@angular/forms'; 3 | import { TranslateService } from '@ngx-translate/core'; 4 | import { LocalStorage } from 'ngx-webstorage'; 5 | import { take } from 'rxjs/operators'; 6 | import { EosService } from '../../services/eos.service'; 7 | 8 | @Component({ 9 | templateUrl: './settings.component.html', 10 | styleUrls: ['./settings.component.scss'] 11 | }) 12 | export class SettingsComponent implements OnInit { 13 | 14 | @LocalStorage() language: string; 15 | languages = LANGUAGES; 16 | apis = APIS; 17 | languageControl: FormControl; 18 | apiControl: FormControl; 19 | 20 | constructor( 21 | private translate: TranslateService, 22 | private eosService: EosService 23 | ) { } 24 | 25 | ngOnInit() { 26 | // initialize language select control 27 | this.languageControl = new FormControl(); 28 | // set initial language select control value with LocalStorage value 29 | this.languageControl.setValue(this.language); 30 | // subscribe to language select control value change 31 | this.languageControl.valueChanges.subscribe(language => { 32 | this.language = language; 33 | this.translate.use(language); 34 | }); 35 | 36 | // setup api control 37 | this.apiControl = new FormControl(); 38 | this.eosService.apiEndpoint$.pipe( 39 | take(1) 40 | ).subscribe(apiEndpoint => { 41 | this.apiControl.setValue(apiEndpoint); 42 | }); 43 | this.apiControl.valueChanges.subscribe(apiEndpoint => { 44 | this.eosService.setApiEndpoint(apiEndpoint); 45 | }); 46 | } 47 | 48 | } 49 | 50 | export const LANGUAGES = [ 51 | { code: 'en', name: 'English' }, 52 | { code: 'es', name: 'Spanish' }, 53 | { code: 'fr', name: 'French' }, 54 | { code: 'hr', name: 'Croatian' }, 55 | { code: 'it', name: 'Italian' }, 56 | { code: 'ko', name: 'Korean' }, 57 | { code: 'de', name: 'German' }, 58 | { code: 'dk', name: 'Danish' }, 59 | { code: 'pt', name: 'Portuguese' }, 60 | { code: 'sl', name: 'Slovenian' }, 61 | { code: 'zh', name: 'Chinese' } 62 | ]; 63 | 64 | export const APIS = [ 65 | { name: 'EOS Dublin', endpoint: 'https://api1.eosdublin.io' }, 66 | { name: 'EOS New York', endpoint: 'http://api.eosnewyork.io' }, 67 | { name: 'EOS Proxy', endpoint: 'https://proxy.eosnode.tools' }, 68 | { name: 'Cypherglass', endpoint: 'http://api.cypherglass.com' } 69 | ] 70 | -------------------------------------------------------------------------------- /src/app/models/Result.ts: -------------------------------------------------------------------------------- 1 | export type Result = { 2 | isError: boolean; 3 | value: T; 4 | } 5 | -------------------------------------------------------------------------------- /src/app/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Result'; 2 | -------------------------------------------------------------------------------- /src/app/producer/producer-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { ProducersComponent } from './producers/producers.component'; 5 | import { ProducerComponent } from './producer/producer.component'; 6 | 7 | const routes: Routes = [ 8 | { 9 | path: '', 10 | pathMatch: 'full', 11 | component: ProducersComponent 12 | }, 13 | { 14 | path: ':id', 15 | component: ProducerComponent 16 | } 17 | ]; 18 | 19 | @NgModule({ 20 | imports: [RouterModule.forChild(routes)], 21 | exports: [RouterModule] 22 | }) 23 | export class ProducerRoutingModule { } 24 | -------------------------------------------------------------------------------- /src/app/producer/producer.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { ProducerRoutingModule } from './producer-routing.module'; 4 | import { AgmCoreModule } from '@agm/core'; 5 | 6 | import { ProducersComponent } from './producers/producers.component'; 7 | import { ProducerComponent } from './producer/producer.component'; 8 | import { VoteProgressBarComponent } from './vote-progress-bar/vote-progress-bar.component'; 9 | import { InformationComponent } from './producer/information/information.component'; 10 | import { NodesComponent } from './producer/nodes/nodes.component'; 11 | 12 | @NgModule({ 13 | imports: [ 14 | SharedModule, 15 | ProducerRoutingModule, 16 | AgmCoreModule.forRoot({ 17 | apiKey: 'AIzaSyAm8XqMj1dCSiEDlfb4c5KlZ9kbcBmTLS0' 18 | }) 19 | ], 20 | declarations: [ 21 | ProducersComponent, 22 | ProducerComponent, 23 | VoteProgressBarComponent, 24 | InformationComponent, 25 | NodesComponent 26 | ] 27 | }) 28 | export class ProducerModule { } 29 | -------------------------------------------------------------------------------- /src/app/producer/producer/information/information.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ 'Producer' | translate }} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
{{ 'Name' | translate }}:{{producer.bpJson.org.candidate_name}}
{{ 'Account' | translate }}:{{producer.account.account_name}} 14 | verified_user 15 |
{{ 'Public Key' | translate }}:{{producer.producer_key}} 20 | verified_user 21 |
{{ 'Votes' | translate }}:{{producer.votes}}%
{{ 'Url' | translate }}: 30 | {{producer.url}} 31 |
{{ 'Position' | translate }}:#{{producer.position}}
{{ 'Daily Reward' | translate }}:{{producer.reward}} EOS
42 |
43 |
44 | -------------------------------------------------------------------------------- /src/app/producer/producer/information/information.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | .mat-icon { 6 | color: #4caf50; 7 | margin-left: 5px; 8 | } 9 | -------------------------------------------------------------------------------- /src/app/producer/producer/information/information.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-producer-information', 5 | templateUrl: './information.component.html', 6 | styleUrls: ['./information.component.scss'] 7 | }) 8 | export class InformationComponent implements OnInit { 9 | 10 | @Input() producer; 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/producer/producer/nodes/nodes.component.html: -------------------------------------------------------------------------------- 1 | 2 | {{ 'Nodes' | translate }} 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/app/producer/producer/nodes/nodes.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } -------------------------------------------------------------------------------- /src/app/producer/producer/nodes/nodes.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-producer-nodes', 5 | templateUrl: './nodes.component.html', 6 | styleUrls: ['./nodes.component.scss'] 7 | }) 8 | export class NodesComponent implements OnInit { 9 | 10 | @Input() location; 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/producer/producer/producer.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Producer' | translate }} 4 | {{producer.account?.account_name}} 5 |

6 |
7 |
8 | 9 | 10 | 11 | Account Raw Data 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/app/producer/producer/producer.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/producer/producer/producer.component.scss -------------------------------------------------------------------------------- /src/app/producer/producer/producer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { Observable, combineLatest, of } from 'rxjs'; 4 | import { map, switchMap, share, catchError } from 'rxjs/operators'; 5 | import { EosService } from '../../services/eos.service'; 6 | import { AppService } from '../../services/app.service'; 7 | 8 | @Component({ 9 | templateUrl: './producer.component.html', 10 | styleUrls: ['./producer.component.scss'] 11 | }) 12 | export class ProducerComponent implements OnInit { 13 | 14 | name$: Observable; 15 | producer$: Observable; 16 | 17 | constructor( 18 | private route: ActivatedRoute, 19 | private eosService: EosService, 20 | private appService: AppService 21 | ) { } 22 | 23 | ngOnInit() { 24 | this.name$ = this.route.params.pipe( 25 | map(params => params.id) 26 | ); 27 | this.producer$ = combineLatest( 28 | this.name$, 29 | this.eosService.getChainStatus(), 30 | this.eosService.getProducers(), 31 | this.name$.pipe( 32 | switchMap(name => this.eosService.getDeferAccount(name)) 33 | ) 34 | ).pipe( 35 | map(([name, chainStatus, producers, account]) => { 36 | const producer = producers.find(producer => producer.owner === name); 37 | const index = producers.findIndex(producer => producer.owner === name); 38 | const votesToRemove = producers.reduce((acc, cur) => { 39 | const percentageVotes = cur.total_votes / chainStatus.total_producer_vote_weight * 100; 40 | if (percentageVotes * 200 < 100) { 41 | acc += parseFloat(cur.total_votes); 42 | } 43 | return acc; 44 | }, 0); 45 | let position = parseInt(index) + 1; 46 | let reward = 0; 47 | let percentageVotes = producer.total_votes / chainStatus.total_producer_vote_weight * 100; 48 | let percentageVotesRewarded = producer.total_votes / (chainStatus.total_producer_vote_weight - votesToRemove) * 100; 49 | if (position < 22) { 50 | reward += 318; 51 | } 52 | reward += percentageVotesRewarded * 200; 53 | if (percentageVotes * 200 < 100) { 54 | reward = 0; 55 | } 56 | return { 57 | ...producer, 58 | account: account, 59 | position: position, 60 | reward: reward.toFixed(0), 61 | votes: percentageVotes.toFixed(2) 62 | } 63 | }), 64 | switchMap(producer => { 65 | if (!producer.url) { 66 | return of(producer); 67 | } else { 68 | return this.appService.getBpJson(producer.url).pipe( 69 | catchError(() => of(null)), 70 | map(bpJson => ({ 71 | ...producer, 72 | bpJson, 73 | location: bpJson && bpJson.nodes && bpJson.nodes[0] && bpJson.nodes[0].location, 74 | validated: bpJson && bpJson.producer_public_key === producer.producer_key && bpJson.producer_account_name === producer.owner 75 | })) 76 | ); 77 | } 78 | }), 79 | share() 80 | ); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/app/producer/producers/producers.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Producers' | translate }} 4 |

5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 19 | 20 | 21 | 22 | 25 | 26 | 27 | 28 | 31 | 32 | 33 | 34 | 37 | 38 | 39 | 40 | 44 | 45 | 46 | 47 | 51 | 52 |
# 17 | {{producer.position}} 18 | {{ 'Name' | translate }} 23 | {{producer.owner}} 24 | {{ 'Url' | translate }} 29 | {{producer.url}} 30 | {{ 'Votes' | translate }} 35 | {{producer.numVotes | number}} 36 | {{ '%' | translate }} 41 | {{producer.votes}} 42 | % 43 | {{ 'Daily Reward' | translate }} 48 | {{producer.reward}} 49 | EOS 50 |
53 |
54 |
55 | -------------------------------------------------------------------------------- /src/app/producer/producers/producers.component.scss: -------------------------------------------------------------------------------- 1 | .mat-row:nth-child(-n+21) { 2 | background-color: #e8f5e9; 3 | } -------------------------------------------------------------------------------- /src/app/producer/producers/producers.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 3 | import { EosService } from '../../services/eos.service'; 4 | import { Observable, of, timer } from 'rxjs'; 5 | import { map, share, switchMap } from 'rxjs/operators'; 6 | import {environment} from '../../../environments/environment'; 7 | 8 | @Component({ 9 | templateUrl: './producers.component.html', 10 | styleUrls: ['./producers.component.scss'] 11 | }) 12 | export class ProducersComponent implements OnInit { 13 | 14 | columnHeaders$: Observable = of(PRODUCERS_COLUMNS); 15 | producers$: Observable; 16 | chainStatus$: Observable; 17 | 18 | constructor( 19 | private breakpointObserver: BreakpointObserver, 20 | private eosService: EosService 21 | ) { } 22 | 23 | ngOnInit() { 24 | this.columnHeaders$ = this.breakpointObserver.observe(Breakpoints.XSmall).pipe( 25 | map(result => result.matches ? PRODUCERS_COLUMNS.filter((c: any) => (c !== 'url' && c !== 'numVotes')) : PRODUCERS_COLUMNS) 26 | ); 27 | this.chainStatus$ = timer(0, 60000).pipe( 28 | switchMap(() => this.eosService.getChainStatus()), 29 | share() 30 | ); 31 | this.producers$ = this.chainStatus$.pipe( 32 | switchMap(chainStatus => this.eosService.getProducers().pipe( 33 | map(producers => { 34 | const votesToRemove = producers.reduce((acc, cur) => { 35 | const percentageVotes = cur.total_votes / chainStatus.total_producer_vote_weight * 100; 36 | if (percentageVotes * 200 < 100) { 37 | acc += parseFloat(cur.total_votes); 38 | } 39 | return acc; 40 | }, 0); 41 | return producers.map((producer, index) => { 42 | let position = parseInt(index) + 1; 43 | let reward = 0; 44 | let percentageVotes = producer.total_votes / chainStatus.total_producer_vote_weight * 100; 45 | let percentageVotesRewarded = producer.total_votes / (chainStatus.total_producer_vote_weight - votesToRemove) * 100; 46 | 47 | if (environment.token === 'TLOS') { 48 | if (position < 22) { 49 | reward = 900; 50 | } else if (position < 52) { 51 | reward = 400; 52 | } 53 | } else { 54 | if (position < 22) { 55 | reward += 318; 56 | } 57 | reward += percentageVotesRewarded * 200; 58 | if (reward < 100) { 59 | reward = 0; 60 | } 61 | } 62 | 63 | return { 64 | ...producer, 65 | position: position, 66 | reward: reward.toFixed(0), 67 | votes: percentageVotes.toFixed(2), 68 | numVotes: (producer.total_votes / this.calculateVoteWeight() / 10000).toFixed(0) 69 | } 70 | }); 71 | }) 72 | )), 73 | share() 74 | ); 75 | } 76 | 77 | private calculateVoteWeight() { 78 | //time epoch: 79 | //https://github.com/EOSIO/eos/blob/master/contracts/eosiolib/time.hpp#L160 80 | //stake to vote 81 | //https://github.com/EOSIO/eos/blob/master/contracts/eosio.system/voting.cpp#L105-L109 82 | let timestamp_epoch: number = 946684800000; 83 | let dates_: number = (Date.now() / 1000) - (timestamp_epoch / 1000); 84 | let weight_: number = Math.floor(dates_ / (86400 * 7)) / 52; //86400 = seconds per day 24*3600 85 | return Math.pow(2, weight_); 86 | } 87 | 88 | } 89 | 90 | export const PRODUCERS_COLUMNS = [ 91 | 'position', 92 | 'owner', 93 | 'url', 94 | 'numVotes', 95 | 'votes', 96 | 'reward' 97 | ]; -------------------------------------------------------------------------------- /src/app/producer/vote-progress-bar/vote-progress-bar.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | Votes: {{ chainNumber | number }} ({{chainPercentage}}%) 4 |
-------------------------------------------------------------------------------- /src/app/producer/vote-progress-bar/vote-progress-bar.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | .vote-progress { 6 | display: block; 7 | position: relative; 8 | height: 24px; 9 | .mat-progress-bar { 10 | position: absolute; 11 | top: 0; 12 | right: 0; 13 | left: 0; 14 | height: 100%; 15 | } 16 | span { 17 | position: absolute; 18 | top: 0; 19 | right: 0; 20 | left: 0; 21 | height: 100%; 22 | line-height: 24px; 23 | text-align: center; 24 | color: #fff; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/app/producer/vote-progress-bar/vote-progress-bar.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnChanges, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-vote-progress-bar', 5 | templateUrl: './vote-progress-bar.component.html', 6 | styleUrls: ['./vote-progress-bar.component.scss'] 7 | }) 8 | export class VoteProgressBarComponent implements OnChanges { 9 | 10 | @Input() chainStatus; 11 | chainPercentage; 12 | chainNumber; 13 | 14 | constructor() { } 15 | 16 | ngOnChanges() { 17 | if (this.chainStatus) { 18 | this.chainPercentage = (this.chainStatus.total_activated_stake / 10000 / 1000011818 * 100).toFixed(2); 19 | this.chainNumber = (this.chainStatus.total_activated_stake / 1000011818 * 100000); 20 | } 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/app/services/app.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { HttpClient } from '@angular/common/http'; 3 | import { EosService } from './eos.service'; 4 | import { Observable, Subject, timer, from, forkJoin, of } from 'rxjs'; 5 | import { map, filter, share, withLatestFrom, switchMap, catchError, take } from 'rxjs/operators'; 6 | import {environment} from '../../environments/environment'; 7 | 8 | const EOS_QUOTE = 60000; 9 | const RAM_QUOTE = 60000; 10 | const GET_INFO_INTERVAL = 5000; 11 | 12 | @Injectable({ 13 | providedIn: 'root' 14 | }) 15 | export class AppService { 16 | 17 | private latestBlockNumberSource = new Subject(); 18 | 19 | latestBlockNumber$ = this.latestBlockNumberSource.asObservable(); 20 | isMaintenance$: Observable; 21 | eosQuote$: Observable; 22 | ramQuote$: Observable; 23 | info$: Observable; 24 | latestBlock$: Observable; 25 | recentBlocks$: Observable; 26 | recentTransactions$: Observable; 27 | 28 | constructor( 29 | private http: HttpClient, 30 | private eosService: EosService 31 | ) { 32 | this.info$ = timer(0, GET_INFO_INTERVAL).pipe( 33 | switchMap(() => this.eosService.getDeferInfo()), 34 | share() 35 | ); 36 | this.latestBlock$ = this.info$.pipe( 37 | switchMap((info: any) => from(this.eosService.getDeferBlock(info.head_block_num))), 38 | share() 39 | ); 40 | this.recentBlocks$ = this.latestBlock$.pipe( 41 | switchMap((block: any) => { 42 | const blockNumber: number = block.block_num; 43 | const blockNumbers: number[] = [blockNumber - 1, blockNumber - 2, blockNumber - 3, blockNumber - 4]; 44 | const blockNumbers$: Observable[] = blockNumbers.map(blockNum => this.eosService.getDeferBlock(blockNum).pipe(catchError(() => of(null)))); 45 | return forkJoin(blockNumbers$).pipe( 46 | map((blocks) => [block, ...blocks].filter(block => block !== null)) 47 | ); 48 | }), 49 | share() 50 | ); 51 | this.recentTransactions$ = this.recentBlocks$.pipe( 52 | map((blocks: any[]) => { 53 | return blocks.reduce((previous, current) => { 54 | const transactions = current.transactions.map(transaction => { 55 | return { 56 | ...transaction, 57 | block_num: current.block_num, 58 | trx: typeof transaction.trx === 'string' ? { id: transaction.trx } : transaction.trx 59 | }; 60 | }) 61 | return previous.concat(transactions); 62 | }, []); 63 | }), 64 | share() 65 | ); 66 | this.isMaintenance$ = this.info$.pipe( 67 | withLatestFrom(this.latestBlockNumber$), 68 | map(([chainStatus, blockNumber]) => { 69 | return (chainStatus.head_block_num - blockNumber) > 600; 70 | }), 71 | share() 72 | ); 73 | this.eosQuote$ = timer(0, EOS_QUOTE).pipe( 74 | switchMap(() => this.getEOSTicker()), 75 | filter(ticker => !!ticker.data), 76 | map(ticker => ticker.data), 77 | share() 78 | ); 79 | this.ramQuote$ = timer(0, RAM_QUOTE).pipe( 80 | switchMap(() => from(this.eosService.eos.getTableRows({ 81 | json: true, 82 | code: "eosio", 83 | scope: "eosio", 84 | table: "rammarket" 85 | }))), 86 | filter((data: any) => data.rows && data.rows.length), 87 | map(data => data.rows[0]), 88 | map(data => { 89 | const base = Number(data.base.balance.replace('RAM', '')); 90 | const quote = Number(data.quote.balance.replace('EOS', '')); 91 | return { 92 | ...data, 93 | price: quote / base 94 | }; 95 | }), 96 | share() 97 | ); 98 | } 99 | 100 | getBlocks(blockNumber?: number, limit = 10): Observable { 101 | let blockNumber$: Observable; 102 | if (blockNumber) { 103 | blockNumber$ = of(blockNumber); 104 | } else { 105 | blockNumber$ = this.info$.pipe( 106 | take(1), 107 | map(info => info.head_block_num) 108 | ); 109 | } 110 | return blockNumber$.pipe( 111 | switchMap(blockNumber => { 112 | let blockNumbers: number[] = []; 113 | for (let i = blockNumber; i > blockNumber - limit && i > 0; i--) { 114 | blockNumbers.push(i); 115 | } 116 | const blockNumbers$: Observable[] = blockNumbers.map(blockNumber => { 117 | return this.eosService.getDeferBlock(blockNumber).pipe( 118 | catchError(() => of(null)) 119 | ); 120 | }); 121 | return forkJoin(blockNumbers$).pipe( 122 | map(blocks => blocks.filter(block => block !== null)) 123 | ); 124 | }) 125 | ); 126 | } 127 | 128 | getTokens(): Observable { 129 | return this.http.get(environment.tokensUrl); 130 | } 131 | 132 | getEOSTicker(): Observable { 133 | return this.http.get(environment.tickerUrl); 134 | } 135 | 136 | getBpJson(url: string): Observable { 137 | return this.http.get(`${url}/bp.json`); 138 | } 139 | 140 | setLatestBlockNumber(blockNumber: number) { 141 | if (blockNumber) { 142 | this.latestBlockNumberSource.next(blockNumber); 143 | } 144 | } 145 | 146 | } 147 | 148 | export interface CMCTicker { 149 | data?: { 150 | name: string; 151 | symbol: string; 152 | quotes: { 153 | USD: { 154 | price: number, 155 | market_cap: number, 156 | volume_24h: number 157 | } 158 | } 159 | }; 160 | metadata?: any 161 | } 162 | -------------------------------------------------------------------------------- /src/app/services/eos.service.ts: -------------------------------------------------------------------------------- 1 | import * as Eos from 'eosjs'; 2 | import { Injectable } from '@angular/core'; 3 | import { HttpClient } from '@angular/common/http'; 4 | import { environment } from '../../environments/environment'; 5 | import { Observable, from, of, defer, combineLatest, BehaviorSubject } from 'rxjs'; 6 | import { map, catchError, switchMap } from 'rxjs/operators'; 7 | import { Result } from '../models'; 8 | import { LoggerService } from './logger.service'; 9 | 10 | @Injectable() 11 | export class EosService { 12 | 13 | private apiEndpointSource = new BehaviorSubject(environment.blockchainUrl); 14 | 15 | public apiEndpoint$ = this.apiEndpointSource.asObservable(); 16 | public eos: any; 17 | 18 | constructor( 19 | private http: HttpClient, 20 | private logger: LoggerService 21 | ) { 22 | this.apiEndpoint$.subscribe(apiEndpoint => { 23 | this.eos = Eos({ 24 | httpEndpoint: apiEndpoint, 25 | blockId: environment.chainId 26 | }); 27 | }); 28 | } 29 | 30 | setApiEndpoint(url: string) { 31 | this.apiEndpointSource.next(url); 32 | } 33 | 34 | // Note: to convert chain promise to cold observable, use defer 35 | 36 | private getResult(source$: Observable): Observable> { 37 | return source$.pipe( 38 | map(data => { 39 | return { 40 | isError: false, 41 | value: data 42 | }; 43 | }), 44 | catchError(error => { 45 | this.logger.error('CHAIN_ERROR', error); 46 | return of({ 47 | isError: true, 48 | value: error 49 | }); 50 | }) 51 | ); 52 | } 53 | 54 | getDeferInfo(): Observable { 55 | return defer(() => from(this.eos.getInfo({}))); 56 | } 57 | 58 | getDeferBlock(id: string | number): Observable { 59 | return defer(() => from(this.eos.getBlock(id))); 60 | } 61 | 62 | getDeferAccount(name: string): Observable { 63 | return defer(() => from(this.eos.getAccount(name))); 64 | } 65 | 66 | getDeferTransaction(id: string): Observable { 67 | return defer(() => from(this.eos.getTransaction(id))); 68 | } 69 | 70 | getAccountRaw(name: string): Observable> { 71 | const getAccount$ = defer(() => from(this.eos.getAccount(name))); 72 | return this.getResult(getAccount$); 73 | } 74 | 75 | getAccountActions(name: string, position = -1, offset = -20): Observable> { 76 | const getAccountActions$ = defer(() => from(this.eos.getActions({ 77 | account_name: name, 78 | pos: position, 79 | offset: offset 80 | }))); 81 | return this.getResult(getAccountActions$.pipe( 82 | map((data: any) => data.actions), 83 | map((actions: any[]) => actions.sort((a, b) => b.account_action_seq - a.account_action_seq)) 84 | )); 85 | } 86 | 87 | getAccountTokens(name: string): Observable> { 88 | const allTokens$: Observable = this.http.get(`https://raw.githubusercontent.com/eoscafe/eos-airdrops/master/tokens.json`); 89 | const getCurrencyBalance = function (token: any, account: string): Observable { 90 | return from(this.eos.getCurrencyBalance(token.account, account, token.symbol)).pipe( 91 | map((balance: string[]) => ({ 92 | ...token, 93 | balance: balance[0] ? Number(balance[0].split(' ', 1)) : 0 94 | })), 95 | catchError(() => of({ 96 | ...token, 97 | balance: 0 98 | })) 99 | ); 100 | }; 101 | const accountTokens$ = allTokens$.pipe( 102 | switchMap(tokens => { 103 | return combineLatest( 104 | tokens.map(token => getCurrencyBalance.bind(this)(token, name)) 105 | ).pipe( 106 | map(tokens => tokens.filter(token => token.balance > 0)) 107 | ) 108 | }) 109 | ); 110 | return this.getResult(accountTokens$); 111 | } 112 | 113 | getAbi(name: string): Observable> { 114 | const getCode$ = defer(() => from(this.eos.getAbi({ 115 | account_name: name 116 | }))); 117 | return this.getResult(getCode$); 118 | } 119 | 120 | getBlockRaw(id: string | number): Observable> { 121 | const getBlock$ = defer(() => from(this.eos.getBlock(id))); 122 | return this.getResult(getBlock$); 123 | } 124 | 125 | getTransactionRaw(blockId: number, id: string): Observable> { 126 | const getTransaction$ = defer(() => from(this.eos.getTransaction({ 127 | id: id, 128 | block_num_hint: blockId 129 | }))); 130 | return this.getResult(getTransaction$); 131 | } 132 | 133 | getProducers() { 134 | return from(this.eos.getTableRows({ 135 | json: true, 136 | code: "eosio", 137 | scope: "eosio", 138 | table: "producers", 139 | limit: 700, 140 | table_key: "" 141 | })).pipe( 142 | map((result: any) => { 143 | return result.rows 144 | .map(row => ({ ...row, total_votes: parseFloat(row.total_votes) })) 145 | .sort((a, b) => b.total_votes - a.total_votes); 146 | }) 147 | ); 148 | } 149 | 150 | getChainStatus() { 151 | return from(this.eos.getTableRows({ 152 | json: true, 153 | code: "eosio", 154 | scope: "eosio", 155 | table: "global", 156 | limit: 1 157 | })).pipe( 158 | map((result: any) => result.rows[0]) 159 | ); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /src/app/services/logger.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | 3 | @Injectable({ 4 | providedIn: 'root' 5 | }) 6 | export class LoggerService { 7 | 8 | constructor() { } 9 | 10 | error(type: string, err: any) { 11 | // TODO: log 12 | console.error(type, err); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/services/scatter.service.ts: -------------------------------------------------------------------------------- 1 | import {Injectable} from '@angular/core'; 2 | import * as Eos from 'eosjs'; 3 | import {LocalStorage} from 'ngx-webstorage'; 4 | 5 | @Injectable() 6 | export class ScatterService { 7 | @LocalStorage() 8 | identity: any; 9 | eos: any; 10 | scatter: any; 11 | network: any; 12 | 13 | load() { 14 | this.scatter = (window).scatter; 15 | 16 | this.network = { 17 | blockchain: 'eos', 18 | host: 'api1.eosdublin.io', 19 | port: 443, 20 | chainId: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906' 21 | }; 22 | if (this.scatter) { 23 | this.eos = this.scatter.eos(this.network, Eos, {chainId: this.network.chainId}, 'https'); 24 | } 25 | 26 | } 27 | 28 | login() { 29 | this.load(); 30 | const requirements = {accounts: [this.network]}; 31 | if (!this.scatter) { 32 | alert("You need to install Scatter to use the form."); 33 | return; 34 | } 35 | return this.scatter.getIdentity(requirements); 36 | } 37 | 38 | logout() { 39 | this.scatter.forgetIdentity(); 40 | } 41 | 42 | isLoggedIn() { 43 | return this.scatter && !!this.scatter.identity; 44 | } 45 | 46 | accountName() { 47 | if (!this.scatter || !this.scatter.identity) { 48 | return; 49 | } 50 | const account = this.scatter.identity.accounts.find(acc => acc.blockchain === 'eos'); 51 | return account.name; 52 | } 53 | 54 | support(amount: string) { 55 | this.load(); 56 | const account = this.scatter.identity.accounts.find(acc => acc.blockchain === 'eos'); 57 | return this.eos.transfer(account.name, 'trackeraegis', amount + " EOS", 'Aegis Support'); 58 | } 59 | 60 | refund() { 61 | this.load(); 62 | const account = this.scatter.identity.accounts.find(acc => acc.blockchain === 'eos'); 63 | const options = {authorization: [`${account.name}@${account.authority}`]}; 64 | return this.eos.contract('trackeraegis').then(contract => contract.refund(account.name, options)); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/app/shared/error/error.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | error 4 |

Oops! Something went wrong.

5 |
6 |
7 | -------------------------------------------------------------------------------- /src/app/shared/error/error.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | padding: 20px; 4 | } 5 | 6 | p { 7 | margin: 0; 8 | color: #f44336; 9 | } 10 | -------------------------------------------------------------------------------- /src/app/shared/error/error.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-error', 5 | templateUrl: './error.component.html', 6 | styleUrls: ['./error.component.scss'] 7 | }) 8 | export class ErrorComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/id64/id64.component.html: -------------------------------------------------------------------------------- 1 |
6 | {{id}} 7 |
8 | -------------------------------------------------------------------------------- /src/app/shared/id64/id64.component.scss: -------------------------------------------------------------------------------- 1 | .truncate { 2 | white-space: nowrap; 3 | overflow: hidden; 4 | text-overflow: ellipsis; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/shared/id64/id64.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnChanges, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'id-64', 5 | templateUrl: './id64.component.html', 6 | styleUrls: ['./id64.component.scss'] 7 | }) 8 | export class Id64Component implements OnChanges { 9 | 10 | @Input() id: string; 11 | @Input() override; 12 | breakpoint; 13 | 14 | constructor() { } 15 | 16 | ngOnChanges() { 17 | this.breakpoint = { ...DEFAULTS, ...this.override }; 18 | } 19 | 20 | } 21 | 22 | const DEFAULTS = { xs: 160, sm: 240, md: 320, lg: 400 }; 23 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/header/header.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 6 | 7 | 8 | {{ appName | translate }} 9 | 10 |
11 | 12 |
13 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/header/header.component.scss: -------------------------------------------------------------------------------- 1 | @import '../../../../themes'; 2 | ; 3 | :host { 4 | display: block; 5 | position: fixed; 6 | top: 0; 7 | left: 0; 8 | right: 0; 9 | z-index: 1000; 10 | } 11 | 12 | header { 13 | height: 100%; 14 | padding: 0 20px; 15 | .mat-icon-button { 16 | margin-right: 10px; 17 | } 18 | .brand { 19 | color: mat-color($mat-eosio, 500); 20 | img { 21 | width: 30px; 22 | margin-right: 5px; 23 | vertical-align: middle; 24 | } 25 | } 26 | .search-collapsed { 27 | width: auto; 28 | } 29 | .search-expanded { 30 | width: 100%; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/header/header.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, EventEmitter } from '@angular/core'; 2 | import { environment } from '../../../../environments/environment'; 3 | 4 | @Component({ 5 | selector: 'app-header', 6 | templateUrl: './header.component.html', 7 | styleUrls: ['./header.component.scss'] 8 | }) 9 | export class HeaderComponent implements OnInit { 10 | 11 | @Output() onMenuToggle = new EventEmitter(); 12 | 13 | logoUrl = environment.logoUrl; 14 | appName = environment.appName; 15 | searchExpanded = false; 16 | 17 | constructor() { } 18 | 19 | ngOnInit() { 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/masterpage.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/masterpage.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | position: absolute; 3 | top: 0; 4 | bottom: 0; 5 | left: 0; 6 | right: 0; 7 | } 8 | 9 | app-header { 10 | height: 50px; 11 | } 12 | 13 | mat-sidenav-container { 14 | padding-top: 50px; 15 | height: 100%; 16 | } 17 | 18 | mat-sidenav { 19 | width: 200px; 20 | } 21 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/masterpage.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 3 | import { Observable, of } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | 6 | @Component({ 7 | selector: 'app-masterpage', 8 | templateUrl: './masterpage.component.html', 9 | styleUrls: ['./masterpage.component.scss'] 10 | }) 11 | export class MasterpageComponent implements OnInit { 12 | 13 | sidenavMode$: Observable = of('over'); 14 | sidenavOpen$: Observable = of(false); 15 | 16 | constructor( 17 | private breakpointObserver: BreakpointObserver, 18 | ) { } 19 | 20 | ngOnInit() { 21 | this.sidenavMode$ = this.breakpointObserver.observe([ 22 | Breakpoints.XSmall, 23 | Breakpoints.Small 24 | ]).pipe( 25 | map(result => result.matches ? 'over' : 'side') 26 | ); 27 | this.sidenavOpen$ = this.breakpointObserver.observe([ 28 | Breakpoints.XSmall, 29 | Breakpoints.Small 30 | ]).pipe( 31 | map(result => result.matches ? false : true) 32 | ); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/search/search.component.html: -------------------------------------------------------------------------------- 1 | 2 | 5 |
6 | search 7 | 8 |
9 |
10 | 11 |
12 |
13 | search 14 | 15 |
16 | 19 |
20 |
-------------------------------------------------------------------------------- /src/app/shared/masterpage/search/search.component.scss: -------------------------------------------------------------------------------- 1 | form { 2 | position: relative; 3 | width: 100%; 4 | height: 40px; 5 | } 6 | 7 | form .mat-icon { 8 | position: absolute; 9 | top: 8px; 10 | left: 12px; 11 | } 12 | 13 | form input { 14 | width: 100%; 15 | height: 100%; 16 | border-radius: 24px; 17 | padding: 8px 16px 8px 40px; 18 | outline: none; 19 | box-sizing: border-box; 20 | border: 1px solid #ccc; 21 | } -------------------------------------------------------------------------------- /src/app/shared/masterpage/search/search.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Output, EventEmitter } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { FormControl } from '@angular/forms'; 4 | 5 | @Component({ 6 | selector: 'app-search', 7 | templateUrl: './search.component.html', 8 | styleUrls: ['./search.component.scss'] 9 | }) 10 | export class SearchComponent implements OnInit { 11 | 12 | @Output() onSearchExpanded = new EventEmitter(); 13 | query: FormControl; 14 | expanded = false; 15 | 16 | constructor( 17 | private router: Router 18 | ) { } 19 | 20 | ngOnInit() { 21 | this.query = new FormControl(); 22 | } 23 | 24 | search() { 25 | if (this.query.value) { 26 | this.router.navigate(['/search'], { 27 | queryParams: { q: this.query.value } 28 | }); 29 | this.query.reset(); 30 | } 31 | } 32 | 33 | expand() { 34 | this.expanded = true; 35 | this.onSearchExpanded.emit(this.expanded); 36 | } 37 | 38 | collapse() { 39 | this.expanded = false; 40 | this.onSearchExpanded.emit(this.expanded); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/sidenav/sidenav.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{nav.icon}} 5 | {{nav.name}} 6 | 7 | 8 | {{nav.icon}} 9 | {{nav.name}} 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/app/shared/masterpage/sidenav/sidenav.component.scss: -------------------------------------------------------------------------------- 1 | .mat-list-item.active { 2 | background-color: #f5f5f5; 3 | } -------------------------------------------------------------------------------- /src/app/shared/masterpage/sidenav/sidenav.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { TranslateService } from '@ngx-translate/core'; 3 | import { environment } from '../../../../environments/environment'; 4 | 5 | @Component({ 6 | selector: 'app-sidenav', 7 | templateUrl: './sidenav.component.html', 8 | styleUrls: ['./sidenav.component.scss'] 9 | }) 10 | export class SidenavComponent implements OnInit { 11 | 12 | navs: { 13 | icon: string; 14 | link: string; 15 | name: string; 16 | external?: boolean; 17 | }[]; 18 | 19 | constructor( 20 | private translate: TranslateService 21 | ) { } 22 | 23 | ngOnInit() { 24 | this.navs = [ 25 | { 26 | icon: 'dashboard', 27 | link: '/', 28 | name: this.translate.instant('Dashboard') 29 | }, 30 | { 31 | icon: 'gavel', 32 | link: '/producers', 33 | name: this.translate.instant('Producers') 34 | }, 35 | { 36 | icon: 'link', 37 | link: '/blocks', 38 | name: this.translate.instant('Blocks') 39 | }, 40 | { 41 | icon: 'list_alt', 42 | link: '/transactions', 43 | name: this.translate.instant('Transactions') 44 | }, 45 | { 46 | icon: 'settings', 47 | link: '/settings', 48 | name: this.translate.instant('Settings') 49 | }, 50 | { 51 | icon: 'account_balance_wallet', 52 | external: true, 53 | link: environment.walletUrl, 54 | name: this.translate.instant('Wallet') 55 | }, 56 | { 57 | icon: 'how_to_vote', 58 | external: true, 59 | link: environment.votingUrl, 60 | name: this.translate.instant('Voting') 61 | } 62 | ]; 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /src/app/shared/pipes/tokb.pipes.ts: -------------------------------------------------------------------------------- 1 | import {Pipe, PipeTransform} from '@angular/core'; 2 | 3 | @Pipe({ 4 | name: 'toKB' 5 | }) 6 | 7 | export class ToKbPipes implements PipeTransform { 8 | transform(value: string): number { 9 | return parseFloat(value)/1024; 10 | } 11 | } -------------------------------------------------------------------------------- /src/app/shared/shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; 4 | import { RouterModule } from '@angular/router'; 5 | import { FlexLayoutModule } from '@angular/flex-layout'; 6 | import { TranslateModule } from '@ngx-translate/core'; 7 | import { MomentModule } from 'ngx-moment'; 8 | import { PrettyJsonModule } from 'angular2-prettyjson'; 9 | import { NgxJsonViewerModule } from 'ngx-json-viewer'; 10 | 11 | import { MatSidenavModule } from '@angular/material/sidenav'; 12 | import { MatListModule } from '@angular/material/list'; 13 | import { MatIconModule } from '@angular/material/icon'; 14 | import { MatToolbarModule } from '@angular/material/toolbar'; 15 | import { MatButtonModule } from '@angular/material/button'; 16 | import { MatProgressSpinnerModule } from '@angular/material/progress-spinner'; 17 | import { MatProgressBarModule } from '@angular/material/progress-bar'; 18 | import { MatCardModule } from '@angular/material/card'; 19 | import { MatTableModule } from '@angular/material/table'; 20 | import { MatExpansionModule } from '@angular/material/expansion'; 21 | import { MatTabsModule } from '@angular/material/tabs'; 22 | import { MatBadgeModule } from '@angular/material/badge'; 23 | 24 | import { TableComponent } from './table/table.component'; 25 | import { MasterpageComponent } from './masterpage/masterpage.component'; 26 | import { HeaderComponent } from './masterpage/header/header.component'; 27 | import { SearchComponent } from './masterpage/search/search.component'; 28 | import { SidenavComponent } from './masterpage/sidenav/sidenav.component'; 29 | import { SpinnerComponent } from './spinner/spinner.component'; 30 | import { ErrorComponent } from './error/error.component'; 31 | import { Id64Component } from './id64/id64.component'; 32 | 33 | import { ToKbPipes } from './pipes/tokb.pipes'; 34 | 35 | const sharedModules = [ 36 | CommonModule, 37 | FormsModule, 38 | ReactiveFormsModule, 39 | RouterModule, 40 | FlexLayoutModule, 41 | TranslateModule, 42 | MomentModule, 43 | PrettyJsonModule, 44 | NgxJsonViewerModule 45 | ]; 46 | 47 | const sharedMaterialModules = [ 48 | MatSidenavModule, 49 | MatListModule, 50 | MatIconModule, 51 | MatToolbarModule, 52 | MatButtonModule, 53 | MatProgressSpinnerModule, 54 | MatProgressBarModule, 55 | MatCardModule, 56 | MatTableModule, 57 | MatExpansionModule, 58 | MatTabsModule, 59 | MatBadgeModule 60 | ]; 61 | 62 | const sharedComponents = [ 63 | TableComponent, 64 | MasterpageComponent, 65 | HeaderComponent, 66 | SearchComponent, 67 | SidenavComponent, 68 | SpinnerComponent, 69 | ErrorComponent, 70 | Id64Component 71 | ]; 72 | 73 | const sharedPipes = [ 74 | ToKbPipes 75 | ]; 76 | 77 | @NgModule({ 78 | imports: [ 79 | ...sharedModules, 80 | ...sharedMaterialModules 81 | ], 82 | declarations: [ 83 | ...sharedComponents, 84 | ...sharedPipes 85 | ], 86 | exports: [ 87 | ...sharedModules, 88 | ...sharedMaterialModules, 89 | ...sharedComponents, 90 | ...sharedPipes 91 | ] 92 | }) 93 | export class SharedModule { } 94 | -------------------------------------------------------------------------------- /src/app/shared/spinner/spinner.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/app/shared/spinner/spinner.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | .mat-progress-spinner { 6 | margin: 50px auto; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/shared/spinner/spinner.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-spinner', 5 | templateUrl: './spinner.component.html', 6 | styleUrls: ['./spinner.component.scss'] 7 | }) 8 | export class SpinnerComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/shared/table/table.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |

4 | {{ title }} 5 |

6 |
7 | 11 | 15 |
16 |
17 | 18 |
19 | 20 |
21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /src/app/shared/table/table.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | 5 | .table-title { 6 | margin: 0 0 5px 10px; 7 | } 8 | 9 | .table-wrapper { 10 | overflow: auto; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/shared/table/table.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, OnChanges, Input, SimpleChanges } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { of } from 'rxjs'; 4 | import { map } from 'rxjs/operators'; 5 | 6 | @Component({ 7 | selector: 'app-table', 8 | templateUrl: './table.component.html', 9 | styleUrls: ['./table.component.scss'] 10 | }) 11 | export class TableComponent implements OnInit, OnChanges { 12 | 13 | @Input() dataSource: any; 14 | @Input() title = ''; 15 | @Input() enablePager = true; 16 | page$ = of(1); 17 | visibility = 'hidden'; 18 | 19 | constructor( 20 | private route: ActivatedRoute, 21 | private router: Router 22 | ) { } 23 | 24 | ngOnInit() { 25 | this.page$ = this.route.queryParams.pipe( 26 | map(queryParams => queryParams.page ? Number(queryParams.page) : 1) 27 | ); 28 | } 29 | 30 | ngOnChanges(changes: SimpleChanges) { 31 | if (!changes.dataSource.firstChange) { 32 | this.visibility = 'hidden'; 33 | } 34 | } 35 | 36 | next(currentPage) { 37 | this.visibility = 'visible'; 38 | this.router.navigate([], { 39 | relativeTo: this.route, 40 | queryParams: { page: currentPage + 1 } 41 | }); 42 | } 43 | 44 | previous(currentPage) { 45 | this.visibility = 'visible'; 46 | this.router.navigate([], { 47 | relativeTo: this.route, 48 | queryParams: { page: currentPage - 1 } 49 | }); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /src/app/support/support-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import {SupportComponent} from './support.component'; 4 | 5 | const routes: Routes = [ 6 | { 7 | path: '', 8 | pathMatch: 'full', 9 | component: SupportComponent 10 | } 11 | ]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule] 16 | }) 17 | export class SupportRoutingModule { } 18 | -------------------------------------------------------------------------------- /src/app/support/support.component.1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |

4 | {{ 'Support' | translate }} 5 | {{contract}} 6 |

7 |
8 |
9 |
10 | 11 | 12 | ❤️ {{ 'Support' | translate }} 13 | 14 | 15 | ✨️ Here you can find the list of our AWESOME supporters. 16 | 17 | 18 |
    19 |
  • 💰 Each 7 days project will be able to claim 10% from each patron.
  • 20 |
  • 💳 Patrons can refund anytime their remaining money if they want.
  • 21 |
  • 🏆 A list of all times patrons will appear in the History.
  • 22 |
  • 🔑 Transfer EOS to 23 | {{contract}} or use the Login button.
  • 24 |
25 |
26 |
27 | 28 | 29 | 🛠 {{ 'Actions' | translate }} 30 | 31 | 32 | 33 | ℹ️ To become a Patron please login or transfer EOS to 34 | {{contract}} 35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 |
44 | EOS 45 | 47 |
48 |
49 | 50 |
51 |
52 |
53 |
54 |
55 | 56 |
57 |
58 |
59 |
60 |
61 |
62 | 63 | 64 | {{ 'Roadmap' | translate }} 65 | 66 | 67 |
    68 |
  • Migration to Material design
  • 69 |
  • Multiple themes (dark mode)
  • 70 |
  • Curated list of other external tools
  • 71 |
  • SQL Plugin maintenance
  • 72 |
  • Contract verification
  • 73 |
  • Improve translations
  • 74 |
  • Inline actions tracking
  • 75 |
  • Charts
  • 76 |
  • RAM info
  • 77 |
  • Token lists
  • 78 |
  • Allow execute code from ABI
  • 79 |
  • Notifications / Email Alerts
  • 80 |
  • IPFS search
  • 81 |
  • API usable for third parties
  • 82 |
  • DEX search
  • 83 |
84 |
85 |
86 | 87 | 88 | 💎 {{ 'Info' | translate }} 89 | 90 | 91 | 92 | 93 | 94 | 95 | 98 | 99 | 100 | 101 | 102 | 103 |
Receiver: 96 | {{info.receiver}} 97 |
Last Claim:{{info.last_claim}}
104 |
105 | 106 | 107 | 108 |
109 |
110 |
111 |
112 | 113 | 114 | 💰 {{ 'History (Paid)' | translate }} 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 127 | 128 | 129 |
{{ 'Name' | translate }}{{ 'Amount' | translate }}
125 | {{account.name}} 126 | {{account.balance}}
130 |
131 | 132 | 133 | 134 |
135 |
136 | 137 | 138 | 💸 {{ 'Patrons (Pending)' | translate }} 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 151 | 152 | 153 |
{{ 'Name' | translate }}{{ 'Amount' | translate }}
149 | {{account.name}} 150 | {{account.balance}}
154 |
155 | 156 | 157 | 158 |
159 |
160 |
161 |
-------------------------------------------------------------------------------- /src/app/support/support.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |
5 |
6 |

{{ 'Support' | translate }} {{contract}}

7 |
8 | 9 |
10 | 11 |
12 |
13 |
14 |
15 | ❤️ {{ 'Support' | translate }} 16 |
17 | 18 |
19 | 20 |
21 |
    22 |
  • 💰 Each 7 days project will be able to claim 10% from each patron.
  • 23 |
  • 💳 Patrons can refund anytime their remaining money if they want.
  • 24 |
  • 🏆 A list of all times patrons will appear in the History.
  • 25 |
  • 🔑 Transfer EOS to {{contract}} or use the Login button.
  • 26 |
27 |
28 |
29 |
30 | 38 | 39 | 60 |
61 |
62 |
63 | 64 |
65 | 66 |
67 | 68 |
69 | 99 |
100 |
101 | 💎 {{ 'Info' | translate }} 102 |
103 |
104 | 105 |
106 | 107 |
Last Claim: {{info.last_claim}}
108 |
109 |
110 |
111 |
112 |
113 | 114 |
115 |
116 |
117 |
118 | 💰 {{ 'History (Paid)' | translate }} 119 |
120 | 121 |
122 | 123 |
124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 |
{{ 'Name' | translate }}:{{ 'Amount' | translate }}
{{account.name}}{{account.balance}}
135 |
136 | 137 |
138 | 139 |
140 | 141 |
142 | 143 |
144 |
145 |
146 | 💸 {{ 'Patrons (Pending)' | translate }} 147 |
148 | 149 |
150 | 151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 |
{{ 'Name' | translate }}{{ 'Amount' | translate }}
{{account.name}}{{account.balance}}
163 |
164 | 165 |
166 | 167 |
168 | 169 |
170 |
171 | 172 |
173 |
174 | -------------------------------------------------------------------------------- /src/app/support/support.component.scss: -------------------------------------------------------------------------------- 1 | #confetti-holder { 2 | position: absolute; z-index: 99999; 3 | } -------------------------------------------------------------------------------- /src/app/support/support.component.ts: -------------------------------------------------------------------------------- 1 | import {Component, OnInit} from '@angular/core'; 2 | import {EosService} from '../services/eos.service'; 3 | import {ScatterService} from '../services/scatter.service'; 4 | import {timer} from 'rxjs/index'; 5 | import {takeWhile} from 'rxjs/operators'; 6 | 7 | @Component({ 8 | selector: 'app-support', 9 | templateUrl: './support.component.1.html', 10 | styleUrls: ['./support.component.scss'] 11 | }) 12 | export class SupportComponent implements OnInit { 13 | public history = null; 14 | public patrons = null; 15 | public info = null; 16 | public amount = 5; 17 | public alive = false; 18 | public showConfetti = true; 19 | 20 | readonly contract = "trackeraegis"; 21 | 22 | constructor(private eosService: EosService, 23 | private scatterService: ScatterService) { 24 | } 25 | 26 | ngOnInit() { 27 | this.scatterService.load(); 28 | this.loadTables(); 29 | } 30 | 31 | loadTables() { 32 | this.patrons = null; 33 | this.history = null; 34 | this.info = null; 35 | this.alive = false; 36 | 37 | this.eosService.eos.getTableRows( 38 | { 39 | json: true, 40 | code: this.contract, 41 | scope: this.contract, 42 | table: "history", 43 | limit: 500 44 | } 45 | ).then(result => { 46 | this.history = result.rows.sort(this.compare); 47 | }); 48 | 49 | 50 | this.eosService.eos.getTableRows( 51 | { 52 | json: true, 53 | code: this.contract, 54 | scope: this.contract, 55 | table: "patrons", 56 | limit: 500 57 | } 58 | ).then(result => { 59 | this.patrons = result.rows.sort(this.compare); 60 | }); 61 | 62 | this.eosService.eos.getTableRows( 63 | { 64 | json: true, 65 | code: this.contract, 66 | scope: this.contract, 67 | table: "global", 68 | limit: 1 69 | } 70 | ).then(result => { 71 | this.info = result.rows[0]; 72 | }); 73 | } 74 | 75 | isLogged() { 76 | return this.scatterService.isLoggedIn(); 77 | } 78 | 79 | refund() { 80 | this.alive = true; 81 | this.scatterService.refund().then(transaction => { 82 | timer(0, 3000).pipe( 83 | takeWhile(() => this.alive) 84 | ).subscribe(() => { 85 | this.eosService.getDeferTransaction(transaction.transaction_id).subscribe(data => { 86 | if (data) { 87 | this.loadTables(); 88 | } 89 | }); 90 | }); 91 | 92 | }).catch(error => { 93 | alert('Something was wrong with refund.'); 94 | console.log(error); 95 | this.loadTables(); 96 | }); 97 | } 98 | 99 | support(amount: string) { 100 | this.alive = true; 101 | this.scatterService.support(parseFloat(amount).toFixed(4)).then(transaction => { 102 | console.log(transaction); 103 | timer(0, 3000).pipe( 104 | takeWhile(() => this.alive) 105 | ).subscribe(() => { 106 | this.eosService.getDeferTransaction(transaction.transaction_id).subscribe(data => { 107 | if (data) { 108 | 109 | let confettiSettings = { 110 | 'target': 'confetti-holder', 111 | 'max': '140', 112 | 'size': '2', 113 | 'animate': true, 114 | 'props': ['circle', 'square', 'triangle', 'line'], 115 | 'colors': [[165, 104, 246], [230, 61, 135], [0, 199, 228], [253, 214, 126]], 116 | 'clock': '35', 117 | 'width': '1440', 118 | 'height': '702' 119 | }; 120 | 121 | let confetti = new window.ConfettiGenerator(confettiSettings); 122 | confetti.render(); 123 | this.showConfetti = true; 124 | 125 | timer(7000, 0).pipe( 126 | takeWhile(() => this.showConfetti) 127 | ).subscribe(() => { 128 | confetti.clear(); 129 | this.showConfetti = false; 130 | }); 131 | 132 | this.loadTables(); 133 | } 134 | }); 135 | }); 136 | 137 | }).catch(error => { 138 | alert('Something was wrong with transfer.'); 139 | console.log(error); 140 | this.loadTables(); 141 | }); 142 | } 143 | 144 | login() { 145 | this.scatterService.login(); 146 | } 147 | 148 | 149 | private compare(a, b) { 150 | if (a.balance > b.balance) { 151 | return -1; 152 | } 153 | if (a.balance < b.balance) { 154 | return 1; 155 | } 156 | return 0; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/app/support/support.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { SupportRoutingModule } from './support-routing.module'; 4 | 5 | import {SupportComponent} from './support.component'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | SharedModule, 10 | SupportRoutingModule 11 | ], 12 | declarations: [ 13 | SupportComponent 14 | ] 15 | }) 16 | export class SupportModule { } 17 | -------------------------------------------------------------------------------- /src/app/transaction/transaction-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { TransactionsComponent } from './transactions/transactions.component'; 5 | import { TransactionComponent } from './transaction/transaction.component'; 6 | 7 | const routes: Routes = [ 8 | { 9 | path: '', 10 | pathMatch: 'full', 11 | component: TransactionsComponent 12 | }, 13 | { 14 | path: ':blockId/:id', 15 | component: TransactionComponent 16 | } 17 | ]; 18 | 19 | @NgModule({ 20 | imports: [RouterModule.forChild(routes)], 21 | exports: [RouterModule] 22 | }) 23 | export class TransactionRoutingModule { } 24 | -------------------------------------------------------------------------------- /src/app/transaction/transaction.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { SharedModule } from '../shared/shared.module'; 3 | import { TransactionRoutingModule } from './transaction-routing.module'; 4 | import { MatPaginatorModule } from '@angular/material/paginator'; 5 | 6 | import { TransactionsComponent } from './transactions/transactions.component'; 7 | import { TransactionComponent } from './transaction/transaction.component'; 8 | import { InformationComponent } from './transaction/information/information.component'; 9 | import { DataComponent } from './transaction/data/data.component'; 10 | import { ActionsComponent } from './transaction/actions/actions.component'; 11 | 12 | @NgModule({ 13 | imports: [ 14 | SharedModule, 15 | TransactionRoutingModule, 16 | MatPaginatorModule 17 | ], 18 | declarations: [ 19 | TransactionsComponent, 20 | TransactionComponent, 21 | InformationComponent, 22 | DataComponent, 23 | ActionsComponent 24 | ] 25 | }) 26 | export class TransactionModule { } 27 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/actions/actions.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 16 | 17 | 18 | 19 | 24 | 25 | 26 | 27 | 30 | 31 |
{{ 'Index' | translate }} 8 | {{i + 1}} 9 | {{ 'Account' | translate }} 14 | {{action.account}} 15 | {{ 'Authorizations' | translate }} 20 | 21 | {{auth.actor}}@{{auth.permission}} 22 | 23 | {{ 'Name' | translate }} 28 | {{action.name}} 29 |
32 |
33 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/actions/actions.component.scss: -------------------------------------------------------------------------------- 1 | :host { 2 | display: block; 3 | } 4 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/actions/actions.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-transaction-actions', 5 | templateUrl: './actions.component.html', 6 | styleUrls: ['./actions.component.scss'] 7 | }) 8 | export class ActionsComponent implements OnInit { 9 | 10 | @Input() transaction; 11 | actionsColumns = [ 12 | 'index', 13 | 'account', 14 | 'authorization', 15 | 'name' 16 | ]; 17 | 18 | constructor() { } 19 | 20 | ngOnInit() { 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/data/data.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/data/data.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/transaction/transaction/data/data.component.scss -------------------------------------------------------------------------------- /src/app/transaction/transaction/data/data.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-transaction-data', 5 | templateUrl: './data.component.html', 6 | styleUrls: ['./data.component.scss'] 7 | }) 8 | export class DataComponent implements OnInit { 9 | 10 | @Input() transaction; 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/information/information.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
{{ 'Transaction ID' | translate }}:{{transaction.id}}
{{ 'Block Number' | translate }}: 12 | {{transaction.block_num}} 13 |
{{ 'Timestamp' | translate }}:{{transaction.block_time | amFromUtc | date:'MMM d, y, h:mm:ss.SSS a'}}
{{ 'Irreversible' | translate }}:{{transaction.last_irreversible_block > transaction.block_num}}
{{ 'Pending' | translate }}:{{transaction.trx.trx?.delay_sec > 0}}
{{ 'Status' | translate }}:{{transaction.trx.receipt.status}}
{{ 'CPU Usage' | translate }}:{{transaction.trx.receipt.cpu_usage_us | number }} µs
{{ 'NET Usage' | translate }}:{{transaction.trx.receipt.net_usage_words | toKB | number:'1.0-3'}} KB
{{ 'Number of Actions' | translate }}:{{transaction.trx.trx?.actions?.length || 0}}
44 |
45 |
46 |
47 | 48 |
49 |
50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/information/information.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/transaction/transaction/information/information.component.scss -------------------------------------------------------------------------------- /src/app/transaction/transaction/information/information.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-transaction-information', 5 | templateUrl: './information.component.html', 6 | styleUrls: ['./information.component.scss'] 7 | }) 8 | export class InformationComponent implements OnInit { 9 | 10 | @Input() transaction; 11 | 12 | constructor() { } 13 | 14 | ngOnInit() { 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/transaction.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Transaction' | translate }} 4 |

5 |
6 | 7 | 8 | 9 | 10 | info 11 | {{ 'Transaction Information' | translate }} 12 | 13 | 14 | 15 | 16 | 17 | code 18 | {{ 'BlockchainRawData' | translate }} 19 | 20 |
21 | 22 |
23 |
24 |
25 | 26 | 27 | 28 |
29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/transaction.component.scss: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/transaction/transaction/transaction.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { EosService } from '../../services/eos.service'; 4 | import { Result } from '../../models'; 5 | import { Observable } from 'rxjs'; 6 | import { switchMap } from 'rxjs/operators'; 7 | 8 | @Component({ 9 | templateUrl: './transaction.component.html', 10 | styleUrls: ['./transaction.component.scss'] 11 | }) 12 | export class TransactionComponent implements OnInit { 13 | 14 | transaction$: Observable>; 15 | 16 | constructor( 17 | private route: ActivatedRoute, 18 | private eosService: EosService 19 | ) { } 20 | 21 | ngOnInit() { 22 | this.transaction$ = this.route.params.pipe( 23 | switchMap(params => this.eosService.getTransactionRaw(+params.blockId, params.id)) 24 | ); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/app/transaction/transactions/transactions.component.html: -------------------------------------------------------------------------------- 1 | 2 |

3 | {{ 'Transactions' | translate }} 4 |

5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | Block #{{block.block_num}} 13 | 14 | 15 | {{block.transactions.length}} transactions 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 32 | 33 | 34 | 35 | 38 | 39 | 40 | 41 | 44 | 45 | 46 | 47 | 50 | 51 |
{{ 'Transaction ID' | translate }} 28 | 29 | 30 | 31 | {{ 'CPU Usage' | translate }} 36 | {{transaction.cpu_usage_us | number }} µs 37 | {{ 'NET Usage' | translate }} 42 | {{transaction.net_usage_words | toKB | number:'1.0-3'}} KB 43 | {{ 'Actions' | translate }} 48 | {{transaction.trx.transaction?.actions?.length || 0}} 49 |
52 |
53 |
54 |
55 |
56 | 57 |
58 | 59 | 60 | 61 |
62 | -------------------------------------------------------------------------------- /src/app/transaction/transactions/transactions.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/app/transaction/transactions/transactions.component.scss -------------------------------------------------------------------------------- /src/app/transaction/transactions/transactions.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout'; 3 | import { Observable, of } from 'rxjs'; 4 | import { map, tap } from 'rxjs/operators'; 5 | import { AppService } from '../../services/app.service'; 6 | 7 | @Component({ 8 | templateUrl: './transactions.component.html', 9 | styleUrls: ['./transactions.component.scss'] 10 | }) 11 | export class TransactionsComponent implements OnInit { 12 | 13 | columnHeaders$: Observable = of(DEFAULT_HEADERS); 14 | blocks$: Observable; 15 | pageIndex = 0; 16 | pageSize = 10; 17 | total = 0; 18 | 19 | constructor( 20 | private breakpointObserver: BreakpointObserver, 21 | private appService: AppService 22 | ) { } 23 | 24 | ngOnInit() { 25 | this.columnHeaders$ = this.breakpointObserver.observe(Breakpoints.XSmall).pipe( 26 | map(result => result.matches ? XSMALL_HEADERS : DEFAULT_HEADERS) 27 | ); 28 | this.blocks$ = this.appService.getBlocks(this.pageIndex, this.pageSize).pipe( 29 | tap(blocks => { 30 | this.total = blocks[0].block_num; 31 | }) 32 | ); 33 | } 34 | 35 | onPaging(pageEvent) { 36 | this.pageIndex = pageEvent.pageIndex; 37 | this.blocks$ = this.appService.getBlocks(pageEvent.length - pageEvent.pageSize * pageEvent.pageIndex); 38 | } 39 | 40 | } 41 | 42 | const DEFAULT_HEADERS = [ 43 | 'id', 44 | 'cpu', 45 | 'net', 46 | 'actions' 47 | ]; 48 | 49 | const XSMALL_HEADERS = [ 50 | 'id', 51 | 'actions' 52 | ]; 53 | -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/assets/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/assets/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2 -------------------------------------------------------------------------------- /src/assets/fonts/fonts.css: -------------------------------------------------------------------------------- 1 | /* fallback */ 2 | @font-face { 3 | font-family: 'Material Icons'; 4 | font-style: normal; 5 | font-weight: 400; 6 | src: url(/assets/fonts/flUhRq6tzZclQEJ-Vdg-IuiaDsNcIhQ8tQ.woff2) format('woff2'); 7 | } 8 | 9 | .material-icons { 10 | font-family: 'Material Icons'; 11 | font-weight: normal; 12 | font-style: normal; 13 | font-size: 24px; 14 | line-height: 1; 15 | letter-spacing: normal; 16 | text-transform: none; 17 | display: inline-block; 18 | white-space: nowrap; 19 | word-wrap: normal; 20 | direction: ltr; 21 | -webkit-font-feature-settings: 'liga'; 22 | -webkit-font-smoothing: antialiased; 23 | } 24 | 25 | /* cyrillic-ext */ 26 | @font-face { 27 | font-family: 'Roboto'; 28 | font-style: normal; 29 | font-weight: 300; 30 | src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fCRc4AMP6lbBP.woff2) format('woff2'); 31 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 32 | } 33 | /* cyrillic */ 34 | @font-face { 35 | font-family: 'Roboto'; 36 | font-style: normal; 37 | font-weight: 300; 38 | src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fABc4AMP6lbBP.woff2) format('woff2'); 39 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 40 | } 41 | /* greek-ext */ 42 | @font-face { 43 | font-family: 'Roboto'; 44 | font-style: normal; 45 | font-weight: 300; 46 | src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fCBc4AMP6lbBP.woff2) format('woff2'); 47 | unicode-range: U+1F00-1FFF; 48 | } 49 | /* greek */ 50 | @font-face { 51 | font-family: 'Roboto'; 52 | font-style: normal; 53 | font-weight: 300; 54 | src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fBxc4AMP6lbBP.woff2) format('woff2'); 55 | unicode-range: U+0370-03FF; 56 | } 57 | /* vietnamese */ 58 | @font-face { 59 | font-family: 'Roboto'; 60 | font-style: normal; 61 | font-weight: 300; 62 | src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fCxc4AMP6lbBP.woff2) format('woff2'); 63 | unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; 64 | } 65 | /* latin-ext */ 66 | @font-face { 67 | font-family: 'Roboto'; 68 | font-style: normal; 69 | font-weight: 300; 70 | src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fChc4AMP6lbBP.woff2) format('woff2'); 71 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 72 | } 73 | /* latin */ 74 | @font-face { 75 | font-family: 'Roboto'; 76 | font-style: normal; 77 | font-weight: 300; 78 | src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmSU5fBBc4AMP6lQ.woff2) format('woff2'); 79 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 80 | } 81 | /* cyrillic-ext */ 82 | @font-face { 83 | font-family: 'Roboto'; 84 | font-style: normal; 85 | font-weight: 400; 86 | src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu72xKKTU1Kvnz.woff2) format('woff2'); 87 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 88 | } 89 | /* cyrillic */ 90 | @font-face { 91 | font-family: 'Roboto'; 92 | font-style: normal; 93 | font-weight: 400; 94 | src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu5mxKKTU1Kvnz.woff2) format('woff2'); 95 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 96 | } 97 | /* greek-ext */ 98 | @font-face { 99 | font-family: 'Roboto'; 100 | font-style: normal; 101 | font-weight: 400; 102 | src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7mxKKTU1Kvnz.woff2) format('woff2'); 103 | unicode-range: U+1F00-1FFF; 104 | } 105 | /* greek */ 106 | @font-face { 107 | font-family: 'Roboto'; 108 | font-style: normal; 109 | font-weight: 400; 110 | src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4WxKKTU1Kvnz.woff2) format('woff2'); 111 | unicode-range: U+0370-03FF; 112 | } 113 | /* vietnamese */ 114 | @font-face { 115 | font-family: 'Roboto'; 116 | font-style: normal; 117 | font-weight: 400; 118 | src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7WxKKTU1Kvnz.woff2) format('woff2'); 119 | unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; 120 | } 121 | /* latin-ext */ 122 | @font-face { 123 | font-family: 'Roboto'; 124 | font-style: normal; 125 | font-weight: 400; 126 | src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu7GxKKTU1Kvnz.woff2) format('woff2'); 127 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 128 | } 129 | /* latin */ 130 | @font-face { 131 | font-family: 'Roboto'; 132 | font-style: normal; 133 | font-weight: 400; 134 | src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v18/KFOmCnqEu92Fr1Mu4mxKKTU1Kg.woff2) format('woff2'); 135 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 136 | } 137 | /* cyrillic-ext */ 138 | @font-face { 139 | font-family: 'Roboto'; 140 | font-style: normal; 141 | font-weight: 500; 142 | src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fCRc4AMP6lbBP.woff2) format('woff2'); 143 | unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; 144 | } 145 | /* cyrillic */ 146 | @font-face { 147 | font-family: 'Roboto'; 148 | font-style: normal; 149 | font-weight: 500; 150 | src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fABc4AMP6lbBP.woff2) format('woff2'); 151 | unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; 152 | } 153 | /* greek-ext */ 154 | @font-face { 155 | font-family: 'Roboto'; 156 | font-style: normal; 157 | font-weight: 500; 158 | src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fCBc4AMP6lbBP.woff2) format('woff2'); 159 | unicode-range: U+1F00-1FFF; 160 | } 161 | /* greek */ 162 | @font-face { 163 | font-family: 'Roboto'; 164 | font-style: normal; 165 | font-weight: 500; 166 | src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fBxc4AMP6lbBP.woff2) format('woff2'); 167 | unicode-range: U+0370-03FF; 168 | } 169 | /* vietnamese */ 170 | @font-face { 171 | font-family: 'Roboto'; 172 | font-style: normal; 173 | font-weight: 500; 174 | src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fCxc4AMP6lbBP.woff2) format('woff2'); 175 | unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB; 176 | } 177 | /* latin-ext */ 178 | @font-face { 179 | font-family: 'Roboto'; 180 | font-style: normal; 181 | font-weight: 500; 182 | src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fChc4AMP6lbBP.woff2) format('woff2'); 183 | unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; 184 | } 185 | /* latin */ 186 | @font-face { 187 | font-family: 'Roboto'; 188 | font-style: normal; 189 | font-weight: 500; 190 | src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v18/KFOlCnqEu92Fr1MmEU9fBBc4AMP6lQ.woff2) format('woff2'); 191 | unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; 192 | } -------------------------------------------------------------------------------- /src/assets/i18n/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Übersicht", 3 | "ViewDetails": "Details ansehen", 4 | "Transactions": "Transaktionen", 5 | "Transaction": "Transaktion", 6 | "Accounts": "Konten", 7 | "Account": "Konto", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Nachrichten", 11 | "Message": "Nachricht", 12 | "Producers": "Produzenten", 13 | "Blocks": "Blöcke", 14 | "Block": "Block", 15 | "ViewAll": "Alle ansehen", 16 | "Time": "Zeit", 17 | "Tx": "Tx", 18 | "Producer": "Produzent", 19 | "Msgs": "Nachrichten", 20 | "ToggleNavigation": "Navigation umschalten", 21 | "EOSTracker": "EOS Tracker", 22 | "Wallet": "Wallet", 23 | "SearchBy": "Suche nach Block / Transaktion / Konto", 24 | "Name": "Name", 25 | "Balance": "Guthaben", 26 | "Staked": "Staked", 27 | "Unstaked": "Unstaked", 28 | "CreatedAt": "Erstellt am", 29 | "UpdatedAt": "Geupdated am", 30 | "BlockchainRawData": "Blockchain-Originaldaten", 31 | "Table": "Tabelle", 32 | "Previous": "Vorherige", 33 | "Next": "Nächste", 34 | "BlockId": "Block-ID", 35 | "EOS": "EOS", 36 | "BlockInformation": "Block-Information", 37 | "Number": "Nummer", 38 | "Timestamp": "Zeitstempel", 39 | "MerkleRoot": "Merkle Root", 40 | "TransactionId": "Transaktions-ID", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Handler Account", 43 | "Handler": "Handler", 44 | "Type": "Typ", 45 | "Authorization": "Autorisierung", 46 | "Stats": "Statistiken", 47 | "Search": "Suche", 48 | "Id": "ID", 49 | "Scope": "Geltungsbereich", 50 | "Settings": "Einstellungen", 51 | "Language": "Sprache" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/i18n/dk.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Dashboard", 3 | "ViewDetails": "Se detaljer", 4 | "Transactions": "Transaktioner", 5 | "Transaction": "Transaktion", 6 | "Accounts": "Konti", 7 | "Account": "Konto", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Beskeder", 11 | "Message": "Besked", 12 | "Producers": "Producenter", 13 | "Blocks": "Blokke", 14 | "Block": "Blok", 15 | "ViewAll": "Se alt", 16 | "Time": "Tid", 17 | "Tx": "Tx", 18 | "Producer": "Producer", 19 | "Msgs": "Medd", 20 | "ToggleNavigation": "Navigere", 21 | "EOSTracker": "EOS Tracker", 22 | "Wallet": "Pung", 23 | "SearchBy": "Søg efter Block / Transaktions / Konto", 24 | "Name": "Navn", 25 | "Balance": "Balance", 26 | "Staked": "Stablet", 27 | "Unstaked": "Ikke stablet", 28 | "CreatedAt": "Oprettet den", 29 | "UpdatedAt": "Opdateret den", 30 | "BlockchainRawData": "Blockchain Raw Data", 31 | "Table": "Tabel", 32 | "Previous": "Tidligere", 33 | "Next": "Næte", 34 | "BlockId": "Blok Id", 35 | "EOS": "EOS", 36 | "BlockInformation": "Blok", 37 | "Number": "Nummer", 38 | "Timestamp": "Tidsstempel", 39 | "MerkleRoot": "Merkle root", 40 | "TransactionId": "Transaktions id", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Behandler konto", 43 | "Handler": "Behandler", 44 | "Type": "Type", 45 | "Authorization": "Autorisation", 46 | "Stats": "Statistik", 47 | "Search": "Søg", 48 | "Id": "Id", 49 | "Scope": "Scope", 50 | "Settings": "Indstillinger", 51 | "Language": "Sprog" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/i18n/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Dashboard", 3 | "ViewDetails": "View Details", 4 | "Transactions": "Transactions", 5 | "Transaction": "Transaction", 6 | "Accounts": "Accounts", 7 | "Account": "Account", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Messages", 11 | "Message": "Message", 12 | "Producers": "Producers", 13 | "Blocks": "Blocks", 14 | "Block": "Block", 15 | "ViewAll": "View All", 16 | "Time": "Time", 17 | "Tx": "Tx", 18 | "Producer": "Producer", 19 | "Msgs": "Msgs", 20 | "ToggleNavigation": "Toggle navigation", 21 | "EOSTracker": "EOS Tracker", 22 | "Wallet": "Wallet", 23 | "SearchBy": "Search by Block / Transaction / Account", 24 | "Name": "Name", 25 | "Balance": "Balance", 26 | "Staked": "Staked", 27 | "Unstaked": "Unstaked", 28 | "CreatedAt": "Created At", 29 | "UpdatedAt": "Updated At", 30 | "BlockchainRawData": "Blockchain Raw Data", 31 | "Table": "Table", 32 | "Previous": "Previous", 33 | "Next": "Next", 34 | "BlockId": "Block Id", 35 | "EOS": "EOS", 36 | "BlockInformation": "Block Information", 37 | "Number": "Number", 38 | "Timestamp": "Timestamp", 39 | "MerkleRoot": "Merkle root", 40 | "TransactionId": "Transaction Id", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Handler Account", 43 | "Handler": "Handler", 44 | "Type": "Type", 45 | "Authorization": "Authorization", 46 | "Stats": "Stats", 47 | "Search": "Search", 48 | "Id": "Id", 49 | "Scope": "Scope", 50 | "Settings": "Settings", 51 | "Language": "Language" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/i18n/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Panel", 3 | "ViewDetails": "Ver Detalles", 4 | "Transactions": "Transacciones", 5 | "Transaction": "Transacción", 6 | "Accounts": "Cuentas", 7 | "Account": "Cuenta", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Mensajes", 11 | "Message": "Mensaje", 12 | "Producers": "Productores", 13 | "Blocks": "Bloques", 14 | "Block": "Bloque", 15 | "ViewAll": "Ver Todo", 16 | "Time": "Fecha", 17 | "Tx": "Ts", 18 | "Producer": "Productor", 19 | "Msgs": "Msgs", 20 | "ToggleNavigation": "Expandir navegación", 21 | "EOSTracker": "EOS Tracker", 22 | "Wallet": "Monedero", 23 | "SearchBy": "Buscar por Bloque / Transacción / Cuenta", 24 | "Name": "Nombre", 25 | "Balance": "Balance", 26 | "Staked": "Bloqueado", 27 | "Unstaked": "Desbloqueado", 28 | "CreatedAt": "Creado", 29 | "UpdatedAt": "Actualizado", 30 | "BlockchainRawData": "Respuesta del Blockchain", 31 | "Table": "Tabla", 32 | "Previous": "Anterior", 33 | "Next": "Siguiente", 34 | "BlockId": "Bloque Id", 35 | "EOS": "EOS", 36 | "BlockInformation": "Información del bloque", 37 | "Number": "Número", 38 | "Timestamp": "Fecha", 39 | "MerkleRoot": "Merkle root", 40 | "TransactionId": "Transacción Id", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Cuenta encargada", 43 | "Handler": "Encargado", 44 | "Type": "Tipo", 45 | "Authorization": "Autorización", 46 | "Stats": "Estadísticas", 47 | "Search": "Buscar", 48 | "Id": "Id", 49 | "Scope": "Ámbito", 50 | "Settings": "Configuración", 51 | "Language": "Idioma" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/i18n/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Tableau de bord", 3 | "ViewDetails": "Voir détails", 4 | "Transactions": "Transactions", 5 | "Transaction": "Transaction", 6 | "Accounts": "comptes", 7 | "Account": "compte", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Messages", 11 | "Message": "Message", 12 | "Producers": "Producteurs", 13 | "Blocks": "Blocs", 14 | "Block": "Bloc", 15 | "ViewAll": "Voir Tout", 16 | "Time": "Temps", 17 | "Tx": "Tx", 18 | "Producer": "Producteur", 19 | "Msgs": "Msgs", 20 | "ToggleNavigation": "Basculer la navigation", 21 | "EOSTracker": "EOS Tracker", 22 | "Wallet": "Porte Monnaie", 23 | "SearchBy": "Recherche par bloc / Transaction / Compte", 24 | "Name": "Nom", 25 | "Balance": "Balance", 26 | "Staked": "Jalonné", 27 | "Unstaked": "Unstaked", 28 | "CreatedAt": "Créé à", 29 | "UpdatedAt": "Mis à jour à", 30 | "BlockchainRawData": "donnée brute de Blockchain", 31 | "Table": "Table", 32 | "Previous": "Précédent", 33 | "Next": "Suivant", 34 | "BlockId": "Identifiant de Block", 35 | "EOS": "EOS", 36 | "BlockInformation": "Information de Block", 37 | "Number": "Nombre", 38 | "Timestamp": "Horodatage", 39 | "MerkleRoot": "Merkle root", 40 | "TransactionId": "Identifiant de Transaction", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Gestionnaire du compte", 43 | "Handler": "Gestionnaire", 44 | "Type": "Type", 45 | "Authorization": "Autorisation", 46 | "Stats": "Stats", 47 | "Search": "Chercher", 48 | "Id": "Identifiant", 49 | "Scope": "Scope", 50 | "Settings": "Paramètres", 51 | "Language": "Language" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/i18n/hr.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Upravljačka ploča", 3 | "ViewDetails": "Detaljni pregled", 4 | "Transactions": "Transakcije", 5 | "Transaction": "Transakcija", 6 | "Accounts": "Računi", 7 | "Account": "Račun", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Poruke", 11 | "Message": "Poruka", 12 | "Producers": "Proizvođači", 13 | "Blocks": "Blokovi", 14 | "Block": "Blok", 15 | "ViewAll": "Pogledaj sve", 16 | "Time": "Vrijeme", 17 | "Tx": "Tx", 18 | "Producer": "Proizvođač", 19 | "Msgs": "Poruke", 20 | "ToggleNavigation": "Ukljući navigaciju", 21 | "EOSTracker": "EOS Tracker", 22 | "Wallet": "Novčanik", 23 | "SearchBy": "Traži po transakciji / računu / bloku", 24 | "Name": "Ime", 25 | "Balance": "Stanje", 26 | "Staked": "Na zalihi", 27 | "Unstaked": "Nije na zalihi", 28 | "CreatedAt": "Ustvaren", 29 | "UpdatedAt": "Promijenjen", 30 | "BlockchainRawData": "Sirovi podatci blockchaina", 31 | "Table": "Tabela", 32 | "Previous": "Prijašnji", 33 | "Next": "Sljedeći", 34 | "BlockId": "Block Id", 35 | "EOS": "EOS", 36 | "BlockInformation": "Informacija o bloku", 37 | "Number": "Broj", 38 | "Timestamp": "Vremenski žig", 39 | "MerkleRoot": "Merkle root", 40 | "TransactionId": "Id transakcije", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Račun ročica", 43 | "Handler": "Ročica", 44 | "Type": "Tip", 45 | "Authorization": "Avtorizacija", 46 | "Stats": "Statistika", 47 | "Search": "Traži", 48 | "Id": "Id", 49 | "Scope": "Djelokrug" 50 | } 51 | -------------------------------------------------------------------------------- /src/assets/i18n/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Scrivania", 3 | "ViewDetails": "Vedi dettagli", 4 | "Transactions": "Transazioni", 5 | "Transaction": "Transazione", 6 | "Accounts": "Conti", 7 | "Account": "Conto", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Messaggi", 11 | "Message": "Messaggio", 12 | "Producers": "Produttori", 13 | "Blocks": "Blocchi", 14 | "Block": "Blocco", 15 | "ViewAll": "Vedi tutti", 16 | "Time": "Ora", 17 | "Tx": "Tx", 18 | "Producer": "Produttore", 19 | "Msgs": "Mess", 20 | "ToggleNavigation": "Attiva navigazione", 21 | "EOSTracker": "EOS Tracker", 22 | "Wallet": "Portafogli", 23 | "SearchBy": "Ricerca per blocco / Transazione / Conto", 24 | "Name": "Nome", 25 | "Balance": "Bilancio", 26 | "Staked": "Raggruppare", 27 | "Unstaked": "Dividere", 28 | "CreatedAt": "Creato a", 29 | "UpdatedAt": "Modificato a", 30 | "BlockchainRawData": "Dati grezzi Blockchain", 31 | "Table": "Tabella", 32 | "Previous": "Precedenti", 33 | "Next": "Successivi", 34 | "BlockId": "Id Blocco", 35 | "EOS": "EOS", 36 | "BlockInformation": "Informazioni blocco", 37 | "Number": "Numero", 38 | "Timestamp": "Timestamp", 39 | "MerkleRoot": "Radice di Merkle", 40 | "TransactionId": "Id Transazione", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Conto Compravendite", 43 | "Handler": "Compravendite", 44 | "Type": "Tipo", 45 | "Authorization": "Autorizzazione", 46 | "Stats": "Statistiche", 47 | "Search": "Ricerca", 48 | "Id": "Id", 49 | "Scope": "Area", 50 | "Settings": "Settaggi", 51 | "Language": "Lingua" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/i18n/ko.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "대시보드", 3 | "ViewDetails": "상세보기", 4 | "Transactions": "거래(트랜잭션)", 5 | "Transaction": "거래(트랜잭션)", 6 | "Accounts": "계정", 7 | "Account": "계정", 8 | "Actions": "액션", 9 | "Action": "액션", 10 | "Messages": "메시지", 11 | "Message": "메시지", 12 | "Producers": "블록 프로듀서", 13 | "Blocks": "블록", 14 | "Block": "블록", 15 | "ViewAll": "모두보기", 16 | "Time": "시간", 17 | "Tx": "Tx", 18 | "Producer": "블록 프로듀서", 19 | "Msgs": "메시지", 20 | "ToggleNavigation": "네비게이션 전환", 21 | "EOSTracker": "EOS 트래커", 22 | "Wallet": "지갑", 23 | "SearchBy": "검색(블록, 트랜잭션, 계정)", 24 | "Name": "이름", 25 | "Balance": "잔액", 26 | "Staked": "묶임(Staked)", 27 | "Unstaked": "묶임 해제(Unstaked)", 28 | "CreatedAt": "생성 시각", 29 | "UpdatedAt": "갱신 시각", 30 | "BlockchainRawData": "블록체인 로데이터", 31 | "Table": "테이블", 32 | "Previous": "이전", 33 | "Next": "다음", 34 | "BlockId": "블록 ID", 35 | "EOS": "EOS", 36 | "BlockInformation": "블록 정보", 37 | "Number": "블록 #", 38 | "Timestamp": "생성시각", 39 | "MerkleRoot": "머클 루트", 40 | "TransactionId": "거래 ID", 41 | "ActionIndex": "액션 인덱스", 42 | "HandlerAccount": "핸들러 계정", 43 | "Handler": "핸들러", 44 | "Type": "유형", 45 | "Authorization": "승인권자", 46 | "Stats": "통계", 47 | "Search": "검색", 48 | "Id": "ID", 49 | "Scope": "범위", 50 | "Settings": "설정", 51 | "Language": "언어", 52 | "Votes": "투표", 53 | "Url": "URL", 54 | "Daily Reward": "보상(단위:일)", 55 | "Confirmations": "승인", 56 | "Actions Received": "받은 액션", 57 | "Actions Sent": "보낸 액션", 58 | "Contract": "컨트랙트", 59 | "Tables": "테이블", 60 | "Pending": "대기", 61 | "Expiration": "만료 시간", 62 | "Detail": "상세 정보", 63 | "Transaction Information": "거래 정보" 64 | } 65 | -------------------------------------------------------------------------------- /src/assets/i18n/pt.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Painel de controle", 3 | "ViewDetails": "Ver detalhes", 4 | "Transactions": "Transações", 5 | "Transaction": "Transação", 6 | "Accounts": "Contas", 7 | "Account": "Conta", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Messagem", 11 | "Message": "Messagens", 12 | "Producers": "Produtores", 13 | "Blocks": "Blocos", 14 | "Block": "Bloco", 15 | "ViewAll": "Ver todos", 16 | "Time": "Tempo", 17 | "Tx": "Ts", 18 | "Producer": "Produtor", 19 | "Msgs": "Msgs", 20 | "ToggleNavigation": "Ligar navegação", 21 | "EOSTracker": "Rastreador EOS", 22 | "Wallet": "Carteira", 23 | "SearchBy": "Procurar por Bloco / Transação / Conta", 24 | "Name": "Nome", 25 | "Balance": "Saldo", 26 | "Staked": "Reservado", 27 | "Unstaked": "Não-Reservado", 28 | "CreatedAt": "Criado em", 29 | "UpdatedAt": "Atualizado em", 30 | "BlockchainRawData": "Dados do Blockchain não tratados", 31 | "Table": "Tabela", 32 | "Previous": "Anterior", 33 | "Next": "Próximo", 34 | "BlockId": "Id do Bloco", 35 | "EOS": "EOS", 36 | "BlockInformation": "Informação do bloco", 37 | "Number": "Númbero", 38 | "Timestamp": "Timestamp", 39 | "MerkleRoot": "Raiz Merkle", 40 | "TransactionId": "Id da Transação", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Handler Account", 43 | "Handler": "Handler", 44 | "Type": "Tipo", 45 | "Authorization": "Autorização", 46 | "Stats": "Estatísticas", 47 | "Search": "Procurar", 48 | "Id": "Id", 49 | "Scope": "Escopo", 50 | "Settings": "Configurações", 51 | "Language": "Língua" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/i18n/sl.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "Nadzorna plošča", 3 | "ViewDetails": "Podroben pregled", 4 | "Transactions": "Transakcije", 5 | "Transaction": "Transakcija", 6 | "Accounts": "Računi", 7 | "Account": "Račun", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "Sporočila", 11 | "Message": "Sporočilo", 12 | "Producers": "Proizvajalci", 13 | "Blocks": "Bloki", 14 | "Block": "Blok", 15 | "ViewAll": "Pregled vseh", 16 | "Time": "Čas", 17 | "Tx": "Tx", 18 | "Producer": "Proizvajalec", 19 | "Msgs": "Spor.", 20 | "ToggleNavigation": "Vklopi navigacijo", 21 | "EOSTracker": "EOS Tracker", 22 | "Wallet": "Denarnica", 23 | "SearchBy": "Išči po bloku / transakciji / računu", 24 | "Name": "Naziv", 25 | "Balance": "Stanje", 26 | "Staked": "Na zalogi", 27 | "Unstaked": "Ni na zalogi", 28 | "CreatedAt": "Kreiran ob", 29 | "UpdatedAt": "Spremenjen ob", 30 | "BlockchainRawData": "Blockchain surovi podatki", 31 | "Table": "Tabela", 32 | "Previous": "Predhodni", 33 | "Next": "Naslednji", 34 | "BlockId": "Blok id", 35 | "EOS": "EOS", 36 | "BlockInformation": "blok", 37 | "Number": "Številka", 38 | "Timestamp": "Časovna značka", 39 | "MerkleRoot": "Merklov koren", 40 | "TransactionId": "Id transakcije", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "Račun ročica", 43 | "Handler": "Ročica", 44 | "Type": "Tip", 45 | "Authorization": "Avtorizacija", 46 | "Stats": "Statistika", 47 | "Search": "Iskanje", 48 | "Id": "Id", 49 | "Scope": "Obseg", 50 | "Settings": "Nastavitve", 51 | "Language": "Jezik" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/i18n/zh.json: -------------------------------------------------------------------------------- 1 | { 2 | "Dashboard": "面板", 3 | "ViewDetails": "查看详细", 4 | "Transactions": "交易", 5 | "Transaction": "交易", 6 | "Accounts": "账户", 7 | "Account": "账户", 8 | "Actions": "Actions", 9 | "Action": "Action", 10 | "Messages": "消息", 11 | "Message": "消息", 12 | "Producers": "生产员", 13 | "Blocks": "区块", 14 | "Block": "区块", 15 | "ViewAll": "查看所有", 16 | "Time": "时间", 17 | "Tx": "交易", 18 | "Producer": "生产者", 19 | "Msgs": "记录", 20 | "ToggleNavigation": "切换浏览方式", 21 | "EOSTracker": "EOS追踪仪", 22 | "Wallet": "钱包", 23 | "SearchBy": "根据 区块 / 交易 / 账户 搜索", 24 | "Name": "用户名", 25 | "Balance": "余额", 26 | "Staked": "已受押的", 27 | "Unstaked": "未受押的", 28 | "CreatedAt": "创建时间", 29 | "UpdatedAt": "更新时间", 30 | "BlockchainRawData": "区块链原始数据", 31 | "Table": "表格", 32 | "Previous": "向前", 33 | "Next": "向后", 34 | "BlockId": "区块ID", 35 | "EOS": "EOS", 36 | "BlockInformation": "区块信息", 37 | "Number": "数量", 38 | "Timestamp": "时间戳", 39 | "MerkleRoot": "Merkle根节点", 40 | "TransactionId": "交易Id", 41 | "ActionIndex": "Action Index", 42 | "HandlerAccount": "处理账户", 43 | "Handler": "处理", 44 | "Type": "类型", 45 | "Authorization": "授权", 46 | "Stats": "统计数据", 47 | "Search": "搜索", 48 | "Id": "Id", 49 | "Scope": "范围", 50 | "Settings": "设置", 51 | "Language": "语言" 52 | } 53 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/assets/logo.png -------------------------------------------------------------------------------- /src/assets/nebula.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/assets/nebula.jpg -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | walletUrl: '{WALLET_URL}', 4 | votingUrl: '{VOTING_URL}', 5 | appName: '{APP_NAME}', 6 | logoUrl: '{LOGO_URL}', 7 | blockchainUrl: '{BLOCKCHAIN_URL}', 8 | chainId: '{CHAIN_ID}', 9 | showAds: {SHOW_ADS}, 10 | tokensUrl: '{TOKENS_URL}', 11 | tickerUrl: '{TICKER_URL}', 12 | token: '{TOKEN}' 13 | }; 14 | -------------------------------------------------------------------------------- /src/environments/environment.telos.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | walletUrl: 'https://portal.telosgermany.io', 4 | votingUrl: 'https://telos.eosx.io/tools/vote', 5 | appName: 'Telos Testnet Explorer', 6 | logoUrl: '/assets/logo.png', 7 | blockchainUrl: 'https://testnet.eos.miami', 8 | chainId: 'e17615decaecd202a365f4c029f206eee98511979de8a5756317e2469f2289e3', 9 | showAds: false, 10 | tokensUrl: 'https://raw.githubusercontent.com/eoscafe/eos-airdrops/master/tokens.json', 11 | tickerUrl: 'https://api.coinmarketcap.com/v2/ticker/1765/', 12 | token: 'TLOS' 13 | }; -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false, 8 | walletUrl: 'https://walleteos.com', 9 | votingUrl: 'https://eosportal.io', 10 | appName: 'EOS Tracker', 11 | logoUrl: '/assets/logo.png', 12 | blockchainUrl: 'https://proxy.eosnode.tools', 13 | chainId: 'aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906', 14 | showAds: true, 15 | tokensUrl: 'https://raw.githubusercontent.com/eoscafe/eos-airdrops/master/tokens.json', 16 | tickerUrl: 'https://api.coinmarketcap.com/v2/ticker/1765/', 17 | token: 'EOS' 18 | }; 19 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/EOSEssentials2/EOSTracker2/ef3eadf7c802bd44c44b1c2b1425ca33d6270f14/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | EOS Tracker | Real time viewer for EOSIO Blockchains 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.log(err)); 13 | -------------------------------------------------------------------------------- /src/material.scss: -------------------------------------------------------------------------------- 1 | .mat-table { 2 | width: 100%; 3 | border: 1px solid rgba(0, 0, 0, .12); 4 | } 5 | 6 | .mat-header-cell { 7 | font-size: 14px; 8 | font-weight: 600; 9 | color: inherit; 10 | } 11 | 12 | .mat-headline, 13 | .mat-title, 14 | .mat-subheading-2, 15 | .mat-subheading-1 { 16 | margin: 0; 17 | } 18 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/weak-map'; 35 | // import 'core-js/es6/set'; 36 | 37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 38 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 39 | 40 | /** IE10 and IE11 requires the following for the Reflect API. */ 41 | // import 'core-js/es6/reflect'; 42 | 43 | 44 | /** Evergreen browsers require these. **/ 45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. 46 | import 'core-js/es7/reflect'; 47 | 48 | 49 | /** 50 | * Required to support Web Animations `@angular/platform-browser/animations`. 51 | * Needed for: All but Chrome, Firefox and Opera. http://caniuse.com/#feat=web-animation 52 | **/ 53 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 54 | 55 | 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js/dist/zone'; // Included with Angular CLI. 61 | 62 | 63 | 64 | /*************************************************************************************************** 65 | * APPLICATION IMPORTS 66 | */ 67 | -------------------------------------------------------------------------------- /src/scripts.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/styles.scss: -------------------------------------------------------------------------------- 1 | @import '~normalize.css/normalize.css'; 2 | pre { 3 | margin: 10px !important; 4 | font-size: 12px; 5 | overflow: auto; 6 | } 7 | 8 | .table-container { 9 | overflow: auto; 10 | } 11 | 12 | table { 13 | width: 100%; 14 | border-collapse: collapse; 15 | border-spacing: 0; 16 | th, 17 | td { 18 | height: 40px; 19 | padding: 0 10px !important; 20 | white-space: nowrap; 21 | } 22 | th:first-child, 23 | td:first-child { 24 | padding-left: 15px !important; 25 | } 26 | th:last-child, 27 | td:last-child { 28 | padding-right: 15px !important; 29 | } 30 | tbody tr:nth-child(odd) { 31 | background-color: #f5f5f5; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /src/themes.scss: -------------------------------------------------------------------------------- 1 | @import '~@angular/material/theming'; 2 | 3 | $mat-eosio: ( 4 | 50 : #e9e8ea, 5 | 100 : #c7c5cc, 6 | 200 : #a29faa, 7 | 300 : #7c7987, 8 | 400 : #605c6e, 9 | 500 : #443f54, 10 | 600 : #3e394d, 11 | 700 : #353143, 12 | 800 : #2d293a, 13 | 900 : #1f1b29, 14 | A100 : #9470ff, 15 | A200 : #6e3dff, 16 | A400 : #470aff, 17 | A700 : #3c00f0, 18 | contrast: ( 19 | 50 : #000000, 20 | 100 : #000000, 21 | 200 : #000000, 22 | 300 : #ffffff, 23 | 400 : #ffffff, 24 | 500 : #ffffff, 25 | 600 : #ffffff, 26 | 700 : #ffffff, 27 | 800 : #ffffff, 28 | 900 : #ffffff, 29 | A100 : #000000, 30 | A200 : #ffffff, 31 | A400 : #ffffff, 32 | A700 : #ffffff, 33 | ) 34 | ); 35 | 36 | @include mat-core(); 37 | 38 | $app-light-primary: mat-palette($mat-eosio); 39 | $app-light-accent: mat-palette($mat-eosio, A200, A100, A400); 40 | $app-light-warn: mat-palette($mat-red); 41 | $app-light-theme: mat-light-theme($app-light-primary, $app-light-accent, $app-light-warn); 42 | @include angular-material-theme($app-light-theme); 43 | 44 | $app-dark-primary: mat-palette($mat-eosio); 45 | $app-dark-accent: mat-palette($mat-eosio, A200, A100, A400); 46 | $app-dark-warn: mat-palette($mat-red); 47 | $app-dark-theme: mat-dark-theme($app-dark-primary, $app-dark-accent, $app-dark-warn); 48 | .dark-theme { 49 | @include angular-material-theme($app-dark-theme); 50 | } 51 | 52 | html, 53 | body { 54 | font-family: Roboto, "Helvetica Neue", sans-serif; 55 | margin: 0; 56 | padding: 0; 57 | } 58 | 59 | a { 60 | color: mat-color($app-light-accent); 61 | text-decoration: none; 62 | } 63 | 64 | p { 65 | margin: 0; 66 | padding: 0; 67 | } 68 | -------------------------------------------------------------------------------- /src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "baseUrl": "./", 6 | "module": "es2015", 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "test.ts", 11 | "**/*.spec.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "baseUrl": "./", 6 | "module": "commonjs", 7 | "types": [ 8 | "jasmine", 9 | "node" 10 | ] 11 | }, 12 | "files": [ 13 | "test.ts", 14 | "polyfills.ts" 15 | ], 16 | "include": [ 17 | "**/*.spec.ts", 18 | "**/*.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | 7 | interface Window { ConfettiGenerator: any } 8 | 9 | declare module 'eosjs'; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "sourceMap": true, 6 | "declaration": false, 7 | "moduleResolution": "node", 8 | "emitDecoratorMetadata": true, 9 | "experimentalDecorators": true, 10 | "target": "es5", 11 | "typeRoots": [ 12 | "node_modules/@types" 13 | ], 14 | "lib": [ 15 | "es2017", 16 | "dom" 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "arrow-return-shorthand": true, 7 | "callable-types": true, 8 | "class-name": true, 9 | "comment-format": [ 10 | true, 11 | "check-space" 12 | ], 13 | "curly": true, 14 | "deprecation": { 15 | "severity": "warn" 16 | }, 17 | "eofline": true, 18 | "forin": true, 19 | "import-blacklist": [ 20 | true, 21 | "rxjs/Rx" 22 | ], 23 | "import-spacing": true, 24 | "indent": [ 25 | true, 26 | "spaces" 27 | ], 28 | "interface-over-type-literal": true, 29 | "label-position": true, 30 | "max-line-length": [ 31 | true, 32 | 140 33 | ], 34 | "member-access": false, 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-arg": true, 47 | "no-bitwise": true, 48 | "no-console": [ 49 | true, 50 | "debug", 51 | "info", 52 | "time", 53 | "timeEnd", 54 | "trace" 55 | ], 56 | "no-construct": true, 57 | "no-debugger": true, 58 | "no-duplicate-super": true, 59 | "no-empty": false, 60 | "no-empty-interface": true, 61 | "no-eval": true, 62 | "no-inferrable-types": [ 63 | true, 64 | "ignore-params" 65 | ], 66 | "no-misused-new": true, 67 | "no-non-null-assertion": true, 68 | "no-shadowed-variable": true, 69 | "no-string-literal": false, 70 | "no-string-throw": true, 71 | "no-switch-case-fall-through": true, 72 | "no-trailing-whitespace": true, 73 | "no-unnecessary-initializer": true, 74 | "no-unused-expression": true, 75 | "no-use-before-declare": true, 76 | "no-var-keyword": true, 77 | "object-literal-sort-keys": false, 78 | "one-line": [ 79 | true, 80 | "check-open-brace", 81 | "check-catch", 82 | "check-else", 83 | "check-whitespace" 84 | ], 85 | "prefer-const": true, 86 | "quotemark": [ 87 | true, 88 | "single" 89 | ], 90 | "radix": true, 91 | "semicolon": [ 92 | true, 93 | "always" 94 | ], 95 | "triple-equals": [ 96 | true, 97 | "allow-null-check" 98 | ], 99 | "typedef-whitespace": [ 100 | true, 101 | { 102 | "call-signature": "nospace", 103 | "index-signature": "nospace", 104 | "parameter": "nospace", 105 | "property-declaration": "nospace", 106 | "variable-declaration": "nospace" 107 | } 108 | ], 109 | "unified-signatures": true, 110 | "variable-name": false, 111 | "whitespace": [ 112 | true, 113 | "check-branch", 114 | "check-decl", 115 | "check-operator", 116 | "check-separator", 117 | "check-type" 118 | ], 119 | "directive-selector": [ 120 | true, 121 | "attribute", 122 | "app", 123 | "camelCase" 124 | ], 125 | "component-selector": [ 126 | true, 127 | "element", 128 | "app", 129 | "kebab-case" 130 | ], 131 | "no-output-on-prefix": true, 132 | "use-input-property-decorator": true, 133 | "use-output-property-decorator": true, 134 | "use-host-property-decorator": true, 135 | "no-input-rename": true, 136 | "no-output-rename": true, 137 | "use-life-cycle-interface": true, 138 | "use-pipe-transform-interface": true, 139 | "component-class-suffix": true, 140 | "directive-class-suffix": true 141 | } 142 | } 143 | --------------------------------------------------------------------------------