Add strong typing to variables and functions.

This commit is contained in:
Spencer Ofwiti 2021-04-29 20:10:39 +03:00
parent d0e0108274
commit 9921488a04
37 changed files with 315 additions and 282 deletions

View File

@ -1,10 +1,8 @@
// @ts-ignore
import * as accountIndex from '@src/assets/js/block-sync/data/AccountRegistry.json';
import {environment} from '@src/environments/environment';
const Web3 = require('web3');
import Web3 from 'web3';
const web3 = new Web3(environment.web3Provider);
const abi = accountIndex.default;
const abi: Array<any> = require('@src/assets/js/block-sync/data/AccountRegistry.json');
const web3: Web3 = new Web3(environment.web3Provider);
export class AccountIndex {
contractAddress: string;
@ -30,14 +28,14 @@ export class AccountIndex {
}
public async last(numberOfAccounts: number): Promise<Array<string>> {
const count = await this.totalAccounts();
let lowest = count - numberOfAccounts - 1;
const count: number = await this.totalAccounts();
let lowest: number = count - numberOfAccounts - 1;
if (lowest < 0) {
lowest = 0;
}
let accounts = [];
const accounts: Array<string> = [];
for (let i = count - 1; i > lowest; i--) {
const account = await this.contract.methods.accounts(i).call();
const account: string = await this.contract.methods.accounts(i).call();
accounts.push(account);
}
return accounts;
@ -46,8 +44,7 @@ export class AccountIndex {
public async addToAccountRegistry(address: string): Promise<boolean> {
if (!await this.haveAccount(address)) {
return await this.contract.methods.add(address).send({from: this.signerAddress});
} else {
return await this.haveAccount(address);
}
return true;
}
}

View File

@ -1,10 +1,8 @@
// @ts-ignore
import * as registryClient from '@src/assets/js/block-sync/data/TokenUniqueSymbolIndex.json';
import Web3 from 'web3';
import {environment} from '@src/environments/environment';
const web3 = new Web3(environment.web3Provider);
const abi = registryClient.default;
const abi: Array<any> = require('@src/assets/js/block-sync/data/TokenUniqueSymbolIndex.json');
const web3: Web3 = new Web3(environment.web3Provider);
export class TokenRegistry {
contractAddress: string;
@ -30,7 +28,7 @@ export class TokenRegistry {
}
public async addressOf(identifier: string): Promise<string> {
const id = '0x' + web3.utils.padRight(new Buffer(identifier).toString('hex'), 64);
const id: string = web3.eth.abi.encodeParameter('bytes32', web3.utils.toHex(identifier));
return await this.contract.methods.addressOf(id).call();
}
}

View File

@ -1,5 +1,7 @@
export class ArraySum {
static arraySum(arr: any[]): number {
return arr.reduce((accumulator, current) => accumulator + current, 0);
}
function arraySum(arr: Array<number>): number {
return arr.reduce((accumulator, current) => accumulator + current, 0);
}
export {
arraySum
};

View File

@ -1,6 +1,6 @@
function copyToClipboard(text: any): boolean {
// create our hidden div element
const hiddenCopy = document.createElement('div');
const hiddenCopy: HTMLDivElement = document.createElement('div');
// set the innerHTML of the div
hiddenCopy.innerHTML = text;
// set the position to be absolute and off the screen
@ -21,7 +21,7 @@ function copyToClipboard(text: any): boolean {
// append the div to the body
document.body.appendChild(hiddenCopy);
// create a selection range
const copyRange = document.createRange();
const copyRange: Range = document.createRange();
// set the copy range to be the hidden div
copyRange.selectNode(hiddenCopy);
// add the copy range

View File

@ -3,7 +3,7 @@ import {FormControl, FormGroupDirective, NgForm} from '@angular/forms';
export class CustomErrorStateMatcher implements ErrorStateMatcher{
isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
const isSubmitted = form && form.submitted;
const isSubmitted: boolean = form && form.submitted;
return !!(control && control.invalid && (control.dirty || control.touched || isSubmitted));
}
}

View File

@ -15,7 +15,7 @@ export class CustomValidator {
return null;
}
const valid = regex.test(control.value);
const valid: boolean = regex.test(control.value);
return valid ? null : error;
};
}

View File

@ -1,12 +1,11 @@
function exportCsv(arrayData: any[], filename: string, delimiter = ','): void {
function exportCsv(arrayData: Array<any>, filename: string, delimiter: string = ','): void {
if (arrayData === undefined || arrayData.length === 0) {
alert('No data to be exported!');
return;
}
const header = Object.keys(arrayData[0]).join(delimiter) + '\n';
let csv = header;
let csv: string = Object.keys(arrayData[0]).join(delimiter) + '\n';
arrayData.forEach(obj => {
let row = [];
const row: Array<any> = [];
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
row.push(obj[key]);
@ -15,10 +14,10 @@ function exportCsv(arrayData: any[], filename: string, delimiter = ','): void {
csv += row.join(delimiter) + '\n';
});
const csvData = new Blob([csv], {type: 'text/csv'});
const csvUrl = URL.createObjectURL(csvData);
const csvData: Blob = new Blob([csv], {type: 'text/csv'});
const csvUrl: string = URL.createObjectURL(csvData);
let downloadLink = document.createElement('a');
const downloadLink: HTMLAnchorElement = document.createElement('a');
downloadLink.href = csvUrl;
downloadLink.target = '_blank';
downloadLink.download = filename + '.csv';

View File

@ -3,10 +3,10 @@ import {LoggingService} from '@app/_services/logging.service';
import {HttpErrorResponse} from '@angular/common/http';
import {Router} from '@angular/router';
// A generalized http repsonse error
// A generalized http response error
export class HttpError extends Error {
public status: number
constructor(message, status) {
public status: number;
constructor(message: string, status: number) {
super(message);
this.status = status;
this.name = 'HttpError';
@ -15,7 +15,7 @@ export class HttpError extends Error {
@Injectable()
export class GlobalErrorHandler extends ErrorHandler {
private sentencesForWarningLogging: string[] = [];
private sentencesForWarningLogging: Array<string> = [];
constructor(
private loggingService: LoggingService,
@ -26,15 +26,15 @@ export class GlobalErrorHandler extends ErrorHandler {
handleError(error: Error): void {
this.logError(error);
const message = error.message ? error.message : error.toString();
const message: string = error.message ? error.message : error.toString();
// if (error.status) {
// error = new Error(message);
// }
const errorTraceString = `Error message:\n${message}.\nStack trace: ${error.stack}`;
const errorTraceString: string = `Error message:\n${message}.\nStack trace: ${error.stack}`;
const isWarning = this.isWarning(errorTraceString);
const isWarning: boolean = this.isWarning(errorTraceString);
if (isWarning) {
this.loggingService.sendWarnLevelMessage(errorTraceString, {error});
} else {
@ -45,7 +45,7 @@ export class GlobalErrorHandler extends ErrorHandler {
}
logError(error: any): void {
const route = this.router.url;
const route: string = this.router.url;
if (error instanceof HttpErrorResponse) {
this.loggingService.sendErrorLevelMessage(
`There was an HTTP error on route ${route}.\n${error.message}.\nStatus code: ${(error as HttpErrorResponse).status}`,
@ -60,12 +60,12 @@ export class GlobalErrorHandler extends ErrorHandler {
}
private isWarning(errorTraceString: string): boolean {
let isWarning = true;
let isWarning: boolean = true;
if (errorTraceString.includes('/src/app/')) {
isWarning = false;
}
this.sentencesForWarningLogging.forEach((whiteListSentence) => {
this.sentencesForWarningLogging.forEach((whiteListSentence: string) => {
if (errorTraceString.includes(whiteListSentence)) {
isWarning = true;
}

View File

@ -1,13 +1,13 @@
function HttpGetter(): void {}
HttpGetter.prototype.get = filename => new Promise((whohoo, doh) => {
const xhr = new XMLHttpRequest();
HttpGetter.prototype.get = filename => new Promise((resolve, reject) => {
const xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.addEventListener('load', (e) => {
if (xhr.status === 200) {
whohoo(xhr.responseText);
resolve(xhr.responseText);
return;
}
doh('failed with status ' + xhr.status + ': ' + xhr.statusText);
reject('failed with status ' + xhr.status + ': ' + xhr.statusText);
});
xhr.open('GET', filename);
xhr.send();

View File

@ -3,7 +3,41 @@ import {Injectable} from '@angular/core';
import {Observable, of, throwError} from 'rxjs';
import {delay, dematerialize, materialize, mergeMap} from 'rxjs/operators';
const actions = [
interface Action {
id: number;
user: string;
role: string;
action: string;
approval: boolean;
}
interface Token {
name: string;
symbol: string;
address: string;
supply: string;
decimals: string;
reserves: {};
reserveRatio?: string;
owner?: string;
}
interface Category {
name: string;
products: Array<string>;
}
interface AreaName {
name: string;
locations: Array<string>;
}
interface AreaType {
name: string;
area: Array<string>;
}
const actions: Array<Action> = [
{ id: 1, user: 'Tom', role: 'enroller', action: 'Disburse RSV 100', approval: false },
{ id: 2, user: 'Christine', role: 'admin', action: 'Change user phone number', approval: true },
{ id: 3, user: 'Will', role: 'superadmin', action: 'Reclaim RSV 1000', approval: true },
@ -12,7 +46,7 @@ const actions = [
{ id: 6, user: 'Patience', role: 'enroller', action: 'Change user information', approval: false }
];
const tokens = [
const tokens: Array<Token> = [
{
name: 'Giftable Reserve', symbol: 'GRZ', address: '0xa686005CE37Dce7738436256982C3903f2E4ea8E', supply: '1000000001000000000000000000',
decimals: '18', reserves: {}
@ -44,7 +78,7 @@ const tokens = [
}
];
const categories = [
const categories: Array<Category> = [
{
name: 'system',
products: ['system', 'office main', 'office main phone']
@ -146,7 +180,7 @@ const categories = [
}
];
const areaNames = [
const areaNames: Array<AreaName> = [
{
name: 'Mukuru Nairobi',
locations: ['kayaba', 'kayba', 'kambi', 'mukuru', 'masai', 'hazina', 'south', 'tetra', 'tetrapak', 'ruben', 'rueben', 'kingston',
@ -211,7 +245,7 @@ const areaNames = [
}
];
const areaTypes = [
const areaTypes: Array<AreaType> = [
{
name: 'urban',
area: ['urban', 'nairobi', 'mombasa']
@ -230,9 +264,9 @@ const areaTypes = [
}
];
const accountTypes = ['user', 'cashier', 'vendor', 'tokenagent', 'group'];
const transactionTypes = ['transactions', 'conversions', 'disbursements', 'rewards', 'reclamation'];
const genders = ['male', 'female', 'other'];
const accountTypes: Array<string> = ['user', 'cashier', 'vendor', 'tokenagent', 'group'];
const transactionTypes: Array<string> = ['transactions', 'conversions', 'disbursements', 'rewards', 'reclamation'];
const genders: Array<string> = ['male', 'female', 'other'];
@Injectable()
export class MockBackendInterceptor implements HttpInterceptor {
@ -285,77 +319,77 @@ export class MockBackendInterceptor implements HttpInterceptor {
// route functions
function getActions(): Observable<any> {
function getActions(): Observable<HttpResponse<any>> {
return ok(actions);
}
function getActionById(): Observable<any> {
const queriedAction = actions.find(action => action.id === idFromUrl());
function getActionById(): Observable<HttpResponse<any>> {
const queriedAction: Action = actions.find(action => action.id === idFromUrl());
return ok(queriedAction);
}
function approveAction(): Observable<any> {
const queriedAction = actions.find(action => action.id === idFromUrl());
function approveAction(): Observable<HttpResponse<any>> {
const queriedAction: Action = actions.find(action => action.id === idFromUrl());
queriedAction.approval = body.approval;
const message = `Action approval status set to ${body.approval} successfully!`;
const message: string = `Action approval status set to ${body.approval} successfully!`;
return ok(message);
}
function getTokens(): Observable<any> {
function getTokens(): Observable<HttpResponse<any>> {
return ok(tokens);
}
function getTokenBySymbol(): Observable<any> {
const queriedToken = tokens.find(token => token.symbol === stringFromUrl());
function getTokenBySymbol(): Observable<HttpResponse<any>> {
const queriedToken: Token = tokens.find(token => token.symbol === stringFromUrl());
return ok(queriedToken);
}
function getCategories(): Observable<any> {
const categoryList = categories.map(category => category.name);
function getCategories(): Observable<HttpResponse<any>> {
const categoryList: Array<string> = categories.map(category => category.name);
return ok(categoryList);
}
function getCategoryByProduct(): Observable<any> {
const queriedCategory = categories.find(category => category.products.includes(stringFromUrl()));
function getCategoryByProduct(): Observable<HttpResponse<any>> {
const queriedCategory: Category = categories.find(category => category.products.includes(stringFromUrl()));
return ok(queriedCategory.name);
}
function getAreaNames(): Observable<any> {
const areaNameList = areaNames.map(areaName => areaName.name);
function getAreaNames(): Observable<HttpResponse<any>> {
const areaNameList: Array<string> = areaNames.map(areaName => areaName.name);
return ok(areaNameList);
}
function getAreaNameByLocation(): Observable<any> {
const queriedAreaName = areaNames.find(areaName => areaName.locations.includes(stringFromUrl()));
function getAreaNameByLocation(): Observable<HttpResponse<any>> {
const queriedAreaName: AreaName = areaNames.find(areaName => areaName.locations.includes(stringFromUrl()));
return ok(queriedAreaName.name);
}
function getAreaTypes(): Observable<any> {
const areaTypeList = areaTypes.map(areaType => areaType.name);
function getAreaTypes(): Observable<HttpResponse<any>> {
const areaTypeList: Array<string> = areaTypes.map(areaType => areaType.name);
return ok(areaTypeList);
}
function getAreaTypeByArea(): Observable<any> {
const queriedAreaType = areaTypes.find(areaType => areaType.area.includes(stringFromUrl()));
function getAreaTypeByArea(): Observable<HttpResponse<any>> {
const queriedAreaType: AreaType = areaTypes.find(areaType => areaType.area.includes(stringFromUrl()));
return ok(queriedAreaType.name);
}
function getAccountTypes(): Observable<any> {
function getAccountTypes(): Observable<HttpResponse<any>> {
return ok(accountTypes);
}
function getTransactionTypes(): Observable<any> {
function getTransactionTypes(): Observable<HttpResponse<any>> {
return ok(transactionTypes);
}
function getGenders(): Observable<any> {
function getGenders(): Observable<HttpResponse<any>> {
return ok(genders);
}
// helper functions
function ok(body): Observable<any> {
return of(new HttpResponse({ status: 200, body }));
function ok(responseBody: any): Observable<HttpResponse<any>> {
return of(new HttpResponse({ status: 200, body: responseBody }));
}
function error(message): Observable<any> {
@ -363,12 +397,12 @@ export class MockBackendInterceptor implements HttpInterceptor {
}
function idFromUrl(): number {
const urlParts = url.split('/');
const urlParts: Array<string> = url.split('/');
return parseInt(urlParts[urlParts.length - 1], 10);
}
function stringFromUrl(): string {
const urlParts = url.split('/');
const urlParts: Array<string> = url.split('/');
return urlParts[urlParts.length - 1];
}
}

View File

@ -1,24 +1,23 @@
let objCsv = {
const objCsv: { size: number, dataFile: any } = {
size: 0,
dataFile: []
};
function readCsv(input: any): any {
function readCsv(input: any): Array<any> | void {
if (input.files && input.files[0]) {
let reader = new FileReader();
const reader: FileReader = new FileReader();
reader.readAsBinaryString(input.files[0]);
reader.onload = event => {
objCsv.size = event.total;
// @ts-ignore
objCsv.dataFile = event.target.result;
return parseData(objCsv.dataFile);
};
}
}
function parseData(data: any): any {
let csvData = [];
const lineBreak = data.split('\n');
function parseData(data: any): Array<any> {
const csvData: Array<any> = [];
const lineBreak: Array<any> = data.split('\n');
lineBreak.forEach(res => {
csvData.push(res.split(','));
});

View File

@ -1,7 +1,7 @@
import { validatePerson, validateVcard } from 'cic-schemas-data-validator';
async function personValidation(person: any): Promise<void> {
const personValidationErrors = await validatePerson(person);
const personValidationErrors: any = await validatePerson(person);
if (personValidationErrors) {
personValidationErrors.map(error => console.error(`${error.message}`));
@ -9,7 +9,7 @@ async function personValidation(person: any): Promise<void> {
}
async function vcardValidation(vcard: any): Promise<void> {
const vcardValidationErrors = await validateVcard(vcard);
const vcardValidationErrors: any = await validateVcard(vcard);
if (vcardValidationErrors) {
vcardValidationErrors.map(error => console.error(`${error.message}`));

View File

@ -1,4 +1,4 @@
import {Injectable, isDevMode} from '@angular/core';
import {Injectable} from '@angular/core';
import {
HttpRequest,
HttpHandler,
@ -6,7 +6,7 @@ import {
HttpInterceptor, HttpErrorResponse
} from '@angular/common/http';
import {Observable, throwError} from 'rxjs';
import {catchError, retry} from 'rxjs/operators';
import {catchError} from 'rxjs/operators';
import {ErrorDialogService, LoggingService} from '@app/_services';
import {Router} from '@angular/router';
@ -22,7 +22,7 @@ export class ErrorInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
return next.handle(request).pipe(
catchError((err: HttpErrorResponse) => {
let errorMessage;
let errorMessage: string;
if (err.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
errorMessage = `An error occurred: ${err.error.message}`;

View File

@ -13,7 +13,7 @@ export class HttpConfigInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
// const token = sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'));
// const token: string = sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'));
// if (token) {
// request = request.clone({headers: request.headers.set('Authorization', 'Bearer ' + token)});

View File

@ -19,20 +19,20 @@ export class LoggingInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
return next.handle(request);
// this.loggingService.sendInfoLevelMessage(request);
// const startTime = Date.now();
// let status: string;
// return next.handle(request).pipe(tap(event => {
// status = '';
// if (event instanceof HttpResponse) {
// status = 'succeeded';
// }
// }, error => status = 'failed'),
// finalize(() => {
// const elapsedTime = Date.now() - startTime;
// const message = `${request.method} request for ${request.urlWithParams} ${status} in ${elapsedTime} ms`;
// this.loggingService.sendInfoLevelMessage(message);
// }));
// this.loggingService.sendInfoLevelMessage(request);
// const startTime: number = Date.now();
// let status: string;
//
// return next.handle(request).pipe(tap(event => {
// status = '';
// if (event instanceof HttpResponse) {
// status = 'succeeded';
// }
// }, error => status = 'failed'),
// finalize(() => {
// const elapsedTime: number = Date.now() - startTime;
// const message: string = `${request.method} request for ${request.urlWithParams} ${status} in ${elapsedTime} ms`;
// this.loggingService.sendInfoLevelMessage(message);
// }));
}
}

View File

@ -1,8 +1,9 @@
export interface AccountDetails {
interface AccountDetails {
date_registered: number;
gender: string;
age?: string;
type?: string;
balance?: number;
identities: {
evm: {
'bloxberg:8996': string[];
@ -40,25 +41,25 @@ export interface AccountDetails {
};
}
export interface Signature {
interface Signature {
algo: string;
data: string;
digest: string;
engine: string;
}
export interface Meta {
interface Meta {
data: AccountDetails;
id: string;
signature: Signature;
}
export interface MetaResponse {
interface MetaResponse {
id: string;
m: Meta;
}
export const defaultAccount: AccountDetails = {
const defaultAccount: AccountDetails = {
date_registered: Date.now(),
gender: 'other',
identities: {
@ -94,3 +95,11 @@ export const defaultAccount: AccountDetails = {
}],
},
};
export {
AccountDetails,
Signature,
Meta,
MetaResponse,
defaultAccount
};

View File

@ -1,4 +1,5 @@
export * from '@app/_models/transaction';
export * from '@app/_models/settings';
export * from '@app/_models/user';
export * from '@app/_models/account';
export * from '@app/_models/staff';
export * from '@app/_models/token';

View File

@ -1,4 +1,4 @@
export class Settings {
class Settings {
w3: W3 = {
engine: undefined,
provider: undefined,
@ -12,7 +12,12 @@ export class Settings {
}
}
export class W3 {
class W3 {
engine: any;
provider: any;
}
export {
Settings,
W3
};

View File

@ -1,7 +1,11 @@
export interface Staff {
interface Staff {
comment: string;
email: string;
name: string;
tag: number;
userid: string;
}
export {
Staff
};

View File

@ -1,4 +1,4 @@
export interface Token {
interface Token {
name: string;
symbol: string;
address: string;
@ -13,3 +13,7 @@ export interface Token {
reserveRatio?: string;
owner?: string;
}
export {
Token
};

View File

@ -1,6 +1,6 @@
import {User} from '@app/_models/user';
import {AccountDetails} from '@app/_models/account';
export class BlocksBloom {
class BlocksBloom {
low: number;
blockFilter: string;
blocktxFilter: string;
@ -8,13 +8,13 @@ export class BlocksBloom {
filterRounds: number;
}
export class Token {
class TxToken {
address: string;
name: string;
symbol: string;
}
export class Tx {
class Tx {
block: number;
success: boolean;
timestamp: number;
@ -22,22 +22,30 @@ export class Tx {
txIndex: number;
}
export class Transaction {
class Transaction {
from: string;
sender: User;
sender: AccountDetails;
to: string;
recipient: User;
token: Token;
recipient: AccountDetails;
token: TxToken;
tx: Tx;
value: number;
}
export class Conversion {
destinationToken: Token;
class Conversion {
destinationToken: TxToken;
fromValue: number;
sourceToken: Token;
sourceToken: TxToken;
toValue: number;
trader: string;
user: User;
user: AccountDetails;
tx: Tx;
}
export {
BlocksBloom,
TxToken,
Tx,
Transaction,
Conversion
};

View File

@ -1,22 +0,0 @@
export class User {
dateRegistered: number;
vcard: {
fn: string;
version: string;
tel: [{
meta: {
TYP: string;
};
value: string[];
}];
};
key: {
ethereum: string[];
};
location: {
latitude: string;
longitude: string;
external: {};
};
selling: string[];
}

View File

@ -1,5 +1,5 @@
import { KeyStore } from 'cic-client-meta';
// TODO should we put this on the mutalble key store object
// TODO should we put this on the mutable key store object
import * as openpgp from 'openpgp';
const keyring = new openpgp.Keyring();
@ -76,15 +76,14 @@ class MutablePgpKeyStore implements MutableKeyStore{
}
async isValidKey(key): Promise<boolean> {
// There is supposed to be an opengpg.readKey() method but I can't find it?
// There is supposed to be an openpgp.readKey() method but I can't find it?
const _key = await openpgp.key.readArmored(key);
return !_key.err;
}
async isEncryptedPrivateKey(privateKey: any): Promise<boolean> {
const imported = await openpgp.key.readArmored(privateKey);
for (let i = 0; i < imported.keys.length; i++) {
const key = imported.keys[i];
for (const key of imported.keys) {
if (key.isDecrypted()) {
return false;
}

View File

@ -1,20 +1,19 @@
import { Injectable } from '@angular/core';
import { hobaParseChallengeHeader } from '@src/assets/js/hoba.js';
import { signChallenge } from '@src/assets/js/hoba-pgp.js';
import { environment } from '@src/environments/environment';
import { LoggingService } from '@app/_services/logging.service';
import { MutableKeyStore, MutablePgpKeyStore } from '@app/_pgp';
import { ErrorDialogService } from '@app/_services/error-dialog.service';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { HttpError } from '@app/_helpers/global-error-handler';
import {Injectable} from '@angular/core';
import {hobaParseChallengeHeader} from '@src/assets/js/hoba.js';
import {signChallenge} from '@src/assets/js/hoba-pgp.js';
import {environment} from '@src/environments/environment';
import {LoggingService} from '@app/_services/logging.service';
import {MutableKeyStore, MutablePgpKeyStore} from '@app/_pgp';
import {ErrorDialogService} from '@app/_services/error-dialog.service';
import {HttpClient} from '@angular/common/http';
import {HttpError} from '@app/_helpers/global-error-handler';
@Injectable({
providedIn: 'root'
})
export class AuthService {
sessionToken: any;
sessionLoginCount = 0;
sessionLoginCount: number = 0;
mutableKeyStore: MutableKeyStore;
constructor(
@ -22,18 +21,17 @@ export class AuthService {
private loggingService: LoggingService,
private errorDialogService: ErrorDialogService
) {
this.mutableKeyStore = new MutablePgpKeyStore()
this.mutableKeyStore = new MutablePgpKeyStore();
}
async init(): Promise<void> {
this.mutableKeyStore.loadKeyring();
await this.mutableKeyStore.loadKeyring();
// TODO setting these together should be atomic
if (sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'))) {
this.sessionToken = sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'));
}
if (localStorage.getItem(btoa('CICADA_PRIVATE_KEY'))) {
this.mutableKeyStore.importPrivateKey(localStorage.getItem(btoa('CICADA_PRIVATE_KEY')))
// this.privateKey = localStorage.getItem(btoa('CICADA_PRIVATE_KEY'));
await this.mutableKeyStore.importPrivateKey(localStorage.getItem(btoa('CICADA_PRIVATE_KEY')));
}
}
@ -42,7 +40,7 @@ export class AuthService {
}
getWithToken(): void {
const xhr = new XMLHttpRequest();
const xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.responseType = 'text';
xhr.open('GET', environment.cicMetaUrl + window.location.search.substring(1));
xhr.setRequestHeader('Authorization', 'Bearer ' + this.sessionToken);
@ -59,10 +57,10 @@ export class AuthService {
xhr.send();
}
//TODO renmae to send signed challenge and set session. Also seperate these responsibilities
sendResponse(hobaResponseEncoded): Promise<boolean> {
// TODO rename to send signed challenge and set session. Also separate these responsibilities
sendResponse(hobaResponseEncoded: any): Promise<boolean> {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
const xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.responseType = 'text';
xhr.open('GET', environment.cicMetaUrl + window.location.search.substring(1));
xhr.setRequestHeader('Authorization', 'HOBA ' + hobaResponseEncoded);
@ -80,11 +78,11 @@ export class AuthService {
return resolve(true);
});
xhr.send();
})
});
}
getChallenge(): void {
const xhr = new XMLHttpRequest();
const xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.responseType = 'arraybuffer';
xhr.open('GET', environment.cicMetaUrl + window.location.search.substring(1));
xhr.onload = async (e) => {
@ -117,25 +115,26 @@ export class AuthService {
}
async loginResponse(o): Promise<any> {
return new Promise(async(resolve, reject) => {
async loginResponse(o: { challenge: string, realm: any }): Promise<any> {
return new Promise(async (resolve, reject) => {
try {
const r = await signChallenge(o.challenge,
o.realm,
environment.cicMetaUrl,
this.mutableKeyStore);
const sessionTokenResult = await this.sendResponse(r);
const sessionTokenResult: boolean = await this.sendResponse(r);
} catch (error) {
if (error instanceof HttpError) {
if (error.status === 403) {
this.errorDialogService.openDialog({ message: 'You are not authorized to use this system' })
this.errorDialogService.openDialog({ message: 'You are not authorized to use this system' });
}
if (error.status === 401) {
this.errorDialogService.openDialog({ message: 'Unable to authenticate with the service. ' +
'Please speak with the staff at Grassroots ' +
'Economics for requesting access ' +
'staff@grassrootseconomics.net.' })
this.errorDialogService.openDialog({
message: 'Unable to authenticate with the service. ' +
'Please speak with the staff at Grassroots ' +
'Economics for requesting access ' +
'staff@grassrootseconomics.net.'
});
}
}
// TODO define this error
@ -158,10 +157,10 @@ export class AuthService {
throw Error('The private key is invalid');
}
// TODO leaving this out for now.
//const isEncryptedKeyCheck = await this.mutableKeyStore.isEncryptedPrivateKey(privateKeyArmored);
//if (!isEncryptedKeyCheck) {
// throw Error('The private key doesn\'t have a password!');
//}
// const isEncryptedKeyCheck = await this.mutableKeyStore.isEncryptedPrivateKey(privateKeyArmored);
// if (!isEncryptedKeyCheck) {
// throw Error('The private key doesn\'t have a password!');
// }
const key = await this.mutableKeyStore.importPrivateKey(privateKeyArmored);
localStorage.setItem(btoa('CICADA_PRIVATE_KEY'), privateKeyArmored);
} catch (err) {
@ -182,21 +181,20 @@ export class AuthService {
}
getTrustedUsers(): any {
let trustedUsers = [];
const trustedUsers: Array<any> = [];
this.mutableKeyStore.getPublicKeys().forEach(key => trustedUsers.push(key.users[0].userId));
return trustedUsers;
}
async getPublicKeys(): Promise<any> {
const data = await fetch(environment.publicKeysUrl)
return await fetch(environment.publicKeysUrl)
.then(res => {
if (!res.ok) {
//TODO does angular recommend an error interface?
// TODO does angular recommend an error interface?
throw Error(`${res.statusText} - ${res.status}`);
}
return res.text();
})
return data;
});
}
getPrivateKey(): any {

View File

@ -20,10 +20,10 @@ export class BlockSyncService {
private registryService: RegistryService,
) { }
blockSync(address: string = null, offset: number = 0, limit: number = 100): any {
blockSync(address: string = null, offset: number = 0, limit: number = 100): void {
this.transactionService.resetTransactionsList();
const settings = new Settings(this.scan);
const readyStateElements = { network: 2 };
const settings: Settings = new Settings(this.scan);
const readyStateElements: { network: number } = { network: 2 };
settings.w3.provider = environment.web3Provider;
settings.w3.engine = this.registryService.getWeb3();
settings.registry = this.registryService.getRegistry();
@ -46,7 +46,7 @@ export class BlockSyncService {
readyStateProcessor(settings: Settings, bit: number, address: string, offset: number, limit: number): void {
this.readyState |= bit;
if (this.readyStateTarget === this.readyState && this.readyStateTarget) {
const wHeadSync = new Worker('./../assets/js/block-sync/head.js');
const wHeadSync: Worker = new Worker('./../assets/js/block-sync/head.js');
wHeadSync.onmessage = (m) => {
settings.txHelper.processReceipt(m.data);
};
@ -65,7 +65,7 @@ export class BlockSyncService {
}
}
newTransferEvent(tx): any {
newTransferEvent(tx: any): any {
return new CustomEvent('cic_transfer', {
detail: {
tx,
@ -73,7 +73,7 @@ export class BlockSyncService {
});
}
newConversionEvent(tx): any {
newConversionEvent(tx: any): any {
return new CustomEvent('cic_convert', {
detail: {
tx,
@ -81,8 +81,8 @@ export class BlockSyncService {
});
}
async scan(settings, lo, hi, bloomBlockBytes, bloomBlocktxBytes, bloomRounds): Promise<void> {
const w = new Worker('./../assets/js/block-sync/ondemand.js');
async scan(settings: Settings, lo: number, hi: number, bloomBlockBytes: Uint8Array, bloomBlocktxBytes: Uint8Array, bloomRounds: any): Promise<void> {
const w: Worker = new Worker('./../assets/js/block-sync/ondemand.js');
w.onmessage = (m) => {
settings.txHelper.processReceipt(m.data);
};
@ -99,12 +99,12 @@ export class BlockSyncService {
}
fetcher(settings: Settings, transactionsInfo: any): void {
const blockFilterBinstr = window.atob(transactionsInfo.block_filter);
const bOne = new Uint8Array(blockFilterBinstr.length);
const blockFilterBinstr: string = window.atob(transactionsInfo.block_filter);
const bOne: Uint8Array = new Uint8Array(blockFilterBinstr.length);
bOne.map((e, i, v) => v[i] = blockFilterBinstr.charCodeAt(i));
const blocktxFilterBinstr = window.atob(transactionsInfo.blocktx_filter);
const bTwo = new Uint8Array(blocktxFilterBinstr.length);
const blocktxFilterBinstr: string = window.atob(transactionsInfo.blocktx_filter);
const bTwo: Uint8Array = new Uint8Array(blocktxFilterBinstr.length);
bTwo.map((e, i, v) => v[i] = blocktxFilterBinstr.charCodeAt(i));
settings.scanFilter(settings, transactionsInfo.low, transactionsInfo.high, bOne, bTwo, transactionsInfo.filter_rounds);

View File

@ -1,5 +1,5 @@
import { Injectable } from '@angular/core';
import {MatDialog} from '@angular/material/dialog';
import {MatDialog, MatDialogRef} from '@angular/material/dialog';
import {ErrorDialogComponent} from '@app/shared/error-dialog/error-dialog.component';
@Injectable({
@ -17,7 +17,7 @@ export class ErrorDialogService {
return false;
}
this.isDialogOpen = true;
const dialogRef = this.dialog.open(ErrorDialogComponent, {
const dialogRef: MatDialogRef<any> = this.dialog.open(ErrorDialogComponent, {
width: '300px',
data
});

View File

@ -15,31 +15,31 @@ export class LoggingService {
}
}
sendTraceLevelMessage(message, source, error): void {
sendTraceLevelMessage(message: any, source: any, error: any): void {
this.logger.trace(message, source, error);
}
sendDebugLevelMessage(message, source, error): void {
sendDebugLevelMessage(message: any, source: any, error: any): void {
this.logger.debug(message, source, error);
}
sendInfoLevelMessage(message): void {
sendInfoLevelMessage(message: any): void {
this.logger.info(message);
}
sendLogLevelMessage(message, source, error): void {
sendLogLevelMessage(message: any, source: any, error: any): void {
this.logger.log(message, source, error);
}
sendWarnLevelMessage(message, error): void {
sendWarnLevelMessage(message: any, error: any): void {
this.logger.warn(message, error);
}
sendErrorLevelMessage(message, source, error): void {
sendErrorLevelMessage(message: any, source: any, error: any): void {
this.logger.error(message, source, error);
}
sendFatalLevelMessage(message, source, error): void {
sendFatalLevelMessage(message: any, source: any, error: any): void {
this.logger.fatal(message, source, error);
}
}

View File

@ -1,16 +1,16 @@
import { Injectable } from '@angular/core';
import Web3 from 'web3';
import {environment} from '@src/environments/environment';
import {CICRegistry} from 'cic-client';
import {CICRegistry, FileGetter} from 'cic-client';
import {HttpGetter} from '@app/_helpers';
@Injectable({
providedIn: 'root'
})
export class RegistryService {
web3 = new Web3(environment.web3Provider);
fileGetter = new HttpGetter();
registry = new CICRegistry(this.web3, environment.registryAddress, 'CICRegistry', this.fileGetter,
web3: Web3 = new Web3(environment.web3Provider);
fileGetter: FileGetter = new HttpGetter();
registry: CICRegistry = new CICRegistry(this.web3, environment.registryAddress, 'CICRegistry', this.fileGetter,
['../../assets/js/block-sync/data']);
constructor() {

View File

@ -1,4 +1,4 @@
import { Injectable } from '@angular/core';
import { EventEmitter, Injectable } from '@angular/core';
import {environment} from '@src/environments/environment';
import {BehaviorSubject, Observable} from 'rxjs';
import {CICRegistry} from 'cic-client';
@ -12,9 +12,7 @@ import {RegistryService} from '@app/_services/registry.service';
export class TokenService {
registry: CICRegistry;
tokenRegistry: TokenRegistry;
tokens: any = '';
private tokensList = new BehaviorSubject<any>(this.tokens);
tokensSubject = this.tokensList.asObservable();
LoadEvent: EventEmitter<number> = new EventEmitter<number>();
constructor(
private httpClient: HttpClient,
@ -24,11 +22,12 @@ export class TokenService {
this.registry.load();
this.registry.onload = async (address: string): Promise<void> => {
this.tokenRegistry = new TokenRegistry(await this.registry.getContractAddressByName('TokenRegistry'));
this.LoadEvent.next(Date.now());
};
}
async getTokens(): Promise<any> {
const count = await this.tokenRegistry.totalTokens();
async getTokens(): Promise<Array<Promise<string>>> {
const count: number = await this.tokenRegistry.totalTokens();
return Array.from({length: count}, async (v, i) => await this.tokenRegistry.entry(i));
}

View File

@ -16,6 +16,7 @@ import {LoggingService} from '@app/_services/logging.service';
import {HttpClient} from '@angular/common/http';
import {CICRegistry} from 'cic-client';
import {RegistryService} from '@app/_services/registry.service';
import Web3 from 'web3';
const vCard = require('vcard-parser');
@Injectable({
@ -26,7 +27,7 @@ export class TransactionService {
private transactionList = new BehaviorSubject<any[]>(this.transactions);
transactionsSubject = this.transactionList.asObservable();
userInfo: any;
web3: any;
web3: Web3;
registry: CICRegistry;
constructor(
@ -115,7 +116,7 @@ export class TransactionService {
const data = fromHex(methodSignature + strip0x(abi));
const tx = new Tx(environment.bloxbergChainId);
tx.nonce = await this.web3.eth.getTransactionCount(senderAddress);
tx.gasPrice = await this.web3.eth.getGasPrice();
tx.gasPrice = Number(await this.web3.eth.getGasPrice());
tx.gasLimit = 8000000;
tx.to = fromHex(strip0x(transferAuthAddress));
tx.value = toValue(value);

View File

@ -25,18 +25,13 @@ export class UserService {
signer: Signer;
registry: CICRegistry;
accountsMeta = [];
accounts: any = [];
private accountsList = new BehaviorSubject<any>(this.accounts);
accountsSubject = this.accountsList.asObservable();
accounts: Array<AccountDetails> = [];
private accountsList: BehaviorSubject<Array<AccountDetails>> = new BehaviorSubject<Array<AccountDetails>>(this.accounts);
accountsSubject: Observable<Array<AccountDetails>> = this.accountsList.asObservable();
actions: any = '';
private actionsList = new BehaviorSubject<any>(this.actions);
actionsSubject = this.actionsList.asObservable();
staff: any = '';
private staffList = new BehaviorSubject<any>(this.staff);
staffSubject = this.staffList.asObservable();
actions: Array<any> = [];
private actionsList: BehaviorSubject<any> = new BehaviorSubject<any>(this.actions);
actionsSubject: Observable<Array<any>> = this.actionsList.asObservable();
constructor(
private httpClient: HttpClient,
@ -54,23 +49,23 @@ export class UserService {
}
resetPin(phone: string): Observable<any> {
const params = new HttpParams().set('phoneNumber', phone);
const params: HttpParams = new HttpParams().set('phoneNumber', phone);
return this.httpClient.get(`${environment.cicUssdUrl}/pin`, {params});
}
getAccountStatus(phone: string): any {
const params = new HttpParams().set('phoneNumber', phone);
getAccountStatus(phone: string): Observable<any> {
const params: HttpParams = new HttpParams().set('phoneNumber', phone);
return this.httpClient.get(`${environment.cicUssdUrl}/pin`, {params});
}
getLockedAccounts(offset: number, limit: number): any {
getLockedAccounts(offset: number, limit: number): Observable<any> {
return this.httpClient.get(`${environment.cicUssdUrl}/accounts/locked/${offset}/${limit}`);
}
async changeAccountInfo(address: string, name: string, phoneNumber: string, age: string, type: string, bio: string, gender: string,
businessCategory: string, userLocation: string, location: string, locationType: string
): Promise<any> {
let accountInfo: any = {
const accountInfo: any = {
vcard: {
fn: [{}],
n: [{}],
@ -91,10 +86,10 @@ export class UserService {
accountInfo.location.area_type = locationType;
await vcardValidation(accountInfo.vcard);
accountInfo.vcard = btoa(vCard.generate(accountInfo.vcard));
const accountKey = await User.toKey(address);
const accountKey: string = await User.toKey(address);
this.getAccountDetailsFromMeta(accountKey).pipe(first()).subscribe(async res => {
const syncableAccount: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
let update = [];
const update: Array<ArgPair> = [];
for (const prop in accountInfo) {
update.push(new ArgPair(prop, accountInfo[prop]));
}
@ -110,8 +105,8 @@ export class UserService {
}
async updateMeta(syncableAccount: Syncable, accountKey: string, headers: HttpHeaders): Promise<any> {
const envelope = await this.wrap(syncableAccount , this.signer);
const reqBody = envelope.toJSON();
const envelope: Envelope = await this.wrap(syncableAccount , this.signer);
const reqBody: string = envelope.toJSON();
this.httpClient.put(`${environment.cicMetaUrl}/${accountKey}`, reqBody , { headers }).pipe(first()).subscribe(res => {
this.loggingService.sendInfoLevelMessage(`Response: ${res}`);
});
@ -121,7 +116,7 @@ export class UserService {
this.httpClient.get(`${environment.cicCacheUrl}/actions`).pipe(first()).subscribe(res => this.actionsList.next(res));
}
getActionById(id: string): any {
getActionById(id: string): Observable<any> {
return this.httpClient.get(`${environment.cicCacheUrl}/actions/${id}`);
}
@ -138,14 +133,14 @@ export class UserService {
}
wrap(syncable: Syncable, signer: Signer): Promise<Envelope> {
return new Promise<Envelope>(async (whohoo, doh) => {
return new Promise<Envelope>(async (resolve, reject) => {
syncable.setSigner(signer);
syncable.onwrap = async (env) => {
if (env === undefined) {
doh();
reject();
return;
}
whohoo(env);
resolve(env);
};
await syncable.sign();
});
@ -153,9 +148,9 @@ export class UserService {
async loadAccounts(limit: number = 100, offset: number = 0): Promise<void> {
this.resetAccountsList();
const accountIndexAddress = await this.registry.getContractAddressByName('AccountRegistry');
const accountIndexAddress: string = await this.registry.getContractAddressByName('AccountRegistry');
const accountIndexQuery = new AccountIndex(accountIndexAddress);
const accountAddresses = await accountIndexQuery.last(await accountIndexQuery.totalAccounts());
const accountAddresses: Array<string> = await accountIndexQuery.last(await accountIndexQuery.totalAccounts());
this.loggingService.sendInfoLevelMessage(accountAddresses);
for (const accountAddress of accountAddresses.slice(offset, offset + limit)) {
await this.getAccountByAddress(accountAddress, limit);
@ -163,13 +158,12 @@ export class UserService {
}
async getAccountByAddress(accountAddress: string, limit: number = 100): Promise<Observable<AccountDetails>> {
let accountSubject = new Subject<any>();
let accountSubject: Subject<any> = new Subject<any>();
this.getAccountDetailsFromMeta(await User.toKey(add0x(accountAddress))).pipe(first()).subscribe(async res => {
const account = Envelope.fromJSON(JSON.stringify(res)).unwrap();
this.accountsMeta.push(account);
const account: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
const accountInfo = account.m.data;
await personValidation(accountInfo);
accountInfo.balance = await this.tokenService.getTokenBalance(accountInfo.identities.evm['bloxberg:8996'][0]);
accountInfo.balance = await this.tokenService.getTokenBalance(accountInfo.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0]);
accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));
await vcardValidation(accountInfo.vcard);
this.accounts.unshift(accountInfo);
@ -183,11 +177,11 @@ export class UserService {
}
async getAccountByPhone(phoneNumber: string, limit: number = 100): Promise<Observable<AccountDetails>> {
let accountSubject = new Subject<any>();
let accountSubject: Subject<any> = new Subject<any>();
this.getAccountDetailsFromMeta(await Phone.toKey(phoneNumber)).pipe(first()).subscribe(async res => {
const response = Envelope.fromJSON(JSON.stringify(res)).unwrap();
const address = response.m.data;
const account = await this.getAccountByAddress(address, limit);
const response: Syncable = Envelope.fromJSON(JSON.stringify(res)).unwrap();
const address: string = response.m.data;
const account: Observable<AccountDetails> = await this.getAccountByAddress(address, limit);
account.subscribe(result => {
accountSubject.next(result);
});

View File

@ -22,19 +22,18 @@ export class AppComponent {
) {
(async () => {
try {
await this.authService.mutableKeyStore.loadKeyring();
await this.authService.init();
// this.authService.getPublicKeys()
// .pipe(catchError(async (error) => {
// this.loggingService.sendErrorLevelMessage('Unable to load trusted public keys.', this, {error});
// this.errorDialogService.openDialog({message: 'Trusted keys endpoint can\'t be reached. Please try again later.'});
// })).subscribe(this.authService.mutableKeyStore.importPublicKey);
const publicKeys = await this.authService.getPublicKeys()
const publicKeys = await this.authService.getPublicKeys();
await this.authService.mutableKeyStore.importPublicKey(publicKeys);
} catch(error) {
} catch (error) {
this.errorDialogService.openDialog({message: 'Trusted keys endpoint can\'t be reached. Please try again later.'});
// TODO do something to halt user progress...show a sad cicada page 🦗?
}
})();
this.mediaQuery.addListener(this.onResize);
this.onResize(this.mediaQuery);

View File

@ -27,10 +27,10 @@ export class AuthComponent implements OnInit {
key: ['', Validators.required],
});
await this.authService.init();
//if (this.authService.privateKey !== undefined) {
// const setKey = await this.authService.setKey(this.authService.privateKey);
// }
//}
// if (this.authService.privateKey !== undefined) {
// const setKey = await this.authService.setKey(this.authService.privateKey);
// }
// }
}
get keyFormStub(): any { return this.keyForm.controls; }

View File

@ -9,6 +9,7 @@ import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import {copyToClipboard, CustomErrorStateMatcher, exportCsv} from '@app/_helpers';
import {MatSnackBar} from '@angular/material/snack-bar';
import {add0x, strip0x} from '@src/assets/js/ethtx/dist/hex';
import {environment} from '@src/environments/environment';
@Component({
selector: 'app-account-details',
@ -139,7 +140,7 @@ export class AccountDetailsComponent implements OnInit {
}
viewAccount(account): void {
this.router.navigateByUrl(`/accounts/${strip0x(account.identities.evm['bloxberg:8996'][0])}`);
this.router.navigateByUrl(`/accounts/${strip0x(account.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0])}`);
}
get accountInfoFormStub(): any { return this.accountInfoForm.controls; }

View File

@ -4,6 +4,7 @@ import {CustomErrorStateMatcher} from '@app/_helpers';
import {UserService} from '@app/_services';
import {Router} from '@angular/router';
import {strip0x} from '@src/assets/js/ethtx/dist/hex';
import {environment} from '@src/environments/environment';
@Component({
selector: 'app-account-search',
@ -60,7 +61,7 @@ export class AccountSearchComponent implements OnInit {
(await this.userService.getAccountByPhone(this.phoneSearchFormStub.phoneNumber.value, 100)).subscribe(async res => {
console.log(res);
if (res !== undefined) {
await this.router.navigateByUrl(`/accounts/${strip0x(res.identities.evm['bloxberg:8996'][0])}`);
await this.router.navigateByUrl(`/accounts/${strip0x(res.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0])}`);
} else {
alert('Account not found!');
}
@ -74,7 +75,7 @@ export class AccountSearchComponent implements OnInit {
this.addressSearchLoading = true;
(await this.userService.getAccountByAddress(this.addressSearchFormStub.address.value, 100)).subscribe(async res => {
if (res !== undefined) {
await this.router.navigateByUrl(`/accounts/${strip0x(res.identities.evm['bloxberg:8996'][0])}`);
await this.router.navigateByUrl(`/accounts/${strip0x(res.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0])}`);
} else {
alert('Account not found!');
}

View File

@ -7,6 +7,7 @@ import {Router} from '@angular/router';
import {exportCsv} from '@app/_helpers';
import {strip0x} from '@src/assets/js/ethtx/dist/hex';
import {first} from 'rxjs/operators';
import {environment} from '@src/environments/environment';
@Component({
selector: 'app-accounts',
@ -57,7 +58,7 @@ export class AccountsComponent implements OnInit {
}
async viewAccount(account): Promise<void> {
await this.router.navigateByUrl(`/accounts/${strip0x(account.identities.evm['bloxberg:8996'][0])}`);
await this.router.navigateByUrl(`/accounts/${strip0x(account.identities.evm[`bloxberg:${environment.bloxbergChainId}`][0])}`);
}
filterAccounts(): void {

View File

@ -5,6 +5,7 @@ import {LoggingService, TokenService} from '@app/_services';
import {MatTableDataSource} from '@angular/material/table';
import {Router} from '@angular/router';
import {exportCsv} from '@app/_helpers';
import {TokenRegistry} from '../../_eth';
@Component({
selector: 'app-tokens',
@ -26,13 +27,14 @@ export class TokensComponent implements OnInit {
) { }
async ngOnInit(): Promise<void> {
this.tokenService.LoadEvent.subscribe(async () => {
this.tokens = await this.tokenService.getTokens();
});
this.tokens = await this.tokenService.getTokens();
this.loggingService.sendInfoLevelMessage(this.tokens);
this.tokenService.tokensSubject.subscribe(tokens => {
this.dataSource = new MatTableDataSource(tokens);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
});
this.dataSource = new MatTableDataSource(this.tokens);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
doFilter(value: string): void {