Refactor auth module.
- Switch from form to text field for passphrase input. - Refactor error dialog format. - Send dialog on incorrect parsing of private key. - Refactor block sync service to take parameters.
This commit is contained in:
parent
9fa9852ded
commit
12f4d328bf
@ -4,6 +4,10 @@ An angular admin web client for managing users and transactions in the CIC netwo
|
||||
|
||||
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 10.2.0.
|
||||
|
||||
## Angular CLI
|
||||
|
||||
Run `npm install -g @angular/cli` to install the angular CLI.
|
||||
|
||||
## Development server
|
||||
|
||||
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.
|
||||
|
@ -16,16 +16,13 @@ export class ErrorInterceptor implements HttpInterceptor {
|
||||
|
||||
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||
return next.handle(request).pipe(catchError((err: HttpErrorResponse) => {
|
||||
const data = {
|
||||
this.errorDialogService.openDialog({
|
||||
message: err.error.message || err.statusText,
|
||||
reason: err && err.error && err.error.reason ? err.error.reason : '',
|
||||
status: err.status
|
||||
};
|
||||
this.errorDialogService.openDialog(data);
|
||||
});
|
||||
if ([401, 403].indexOf(err.status) !== -1) {
|
||||
location.reload(true);
|
||||
}
|
||||
// const error = err.error.message || err.statusText;
|
||||
return throwError(err);
|
||||
}));
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {MutableKeyStore, MutablePgpKeyStore} from '@app/_helpers';
|
||||
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 {HttpWrapperService} from '@app/_services/http-wrapper.service';
|
||||
import {MutableKeyStore, MutablePgpKeyStore} from '@app/_pgp';
|
||||
import {ErrorDialogService} from '@app/_services/error-dialog.service';
|
||||
import {first} from 'rxjs/operators';
|
||||
|
||||
@Injectable({
|
||||
@ -18,7 +19,8 @@ export class AuthService {
|
||||
|
||||
constructor(
|
||||
private httpWrapperService: HttpWrapperService,
|
||||
private loggingService: LoggingService
|
||||
private loggingService: LoggingService,
|
||||
private errorDialogService: ErrorDialogService
|
||||
) {
|
||||
if (sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'))) {
|
||||
this.sessionToken = sessionStorage.getItem(btoa('CICADA_SESSION_TOKEN'));
|
||||
@ -29,7 +31,7 @@ export class AuthService {
|
||||
}
|
||||
|
||||
setState(s): void {
|
||||
(document.getElementById('state') as HTMLInputElement).value = s;
|
||||
document.getElementById('state').innerHTML = s;
|
||||
}
|
||||
|
||||
getWithToken(): void {
|
||||
@ -44,7 +46,7 @@ export class AuthService {
|
||||
throw new Error('login rejected');
|
||||
}
|
||||
this.sessionLoginCount++;
|
||||
this.setState('click to perform login ' + this.sessionLoginCount + ' with token ' + this.sessionToken);
|
||||
this.setState('Click button to perform login ' + this.sessionLoginCount + ' with token ' + this.sessionToken);
|
||||
return;
|
||||
});
|
||||
xhr.send();
|
||||
@ -64,7 +66,7 @@ export class AuthService {
|
||||
this.sessionToken = xhr.getResponseHeader('Token');
|
||||
sessionStorage.setItem(btoa('CICADA_SESSION_TOKEN'), this.sessionToken);
|
||||
this.sessionLoginCount++;
|
||||
this.setState('click to perform login ' + this.sessionLoginCount + ' with token ' + this.sessionToken);
|
||||
this.setState('Click button to perform login ' + this.sessionLoginCount + ' with token ' + this.sessionToken);
|
||||
return;
|
||||
});
|
||||
xhr.send();
|
||||
@ -95,8 +97,7 @@ export class AuthService {
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
const o = this.getChallenge();
|
||||
return true;
|
||||
this.getChallenge();
|
||||
} catch (e) {
|
||||
this.loggingService.sendErrorLevelMessage('Login challenge failed', this, {error: e});
|
||||
}
|
||||
@ -113,15 +114,19 @@ export class AuthService {
|
||||
loginView(): void {
|
||||
document.getElementById('one').style.display = 'none';
|
||||
document.getElementById('two').style.display = 'block';
|
||||
this.setState('click to log in with PGP key ' + this.mutableKeyStore.getPrivateKeyId());
|
||||
this.setState('Click button to log in with PGP key ' + this.mutableKeyStore.getPrivateKeyId());
|
||||
}
|
||||
|
||||
async setKey(privateKeyArmored): Promise<boolean> {
|
||||
try {
|
||||
await this.mutableKeyStore.importPrivateKey(privateKeyArmored);
|
||||
localStorage.setItem(btoa('CICADA_PRIVATE_KEY'), privateKeyArmored);
|
||||
} catch (e) {
|
||||
this.loggingService.sendErrorLevelMessage('Failed setting key', this, {error: e});
|
||||
} catch (err) {
|
||||
this.loggingService.sendErrorLevelMessage('Failed setting key', this, {error: err});
|
||||
this.errorDialogService.openDialog({
|
||||
message: `Failed to set key, Enter your private key again. Reason: ${err.error.message || err.statusText}`,
|
||||
status: err.status
|
||||
});
|
||||
return false;
|
||||
}
|
||||
this.loginView();
|
||||
@ -134,10 +139,10 @@ export class AuthService {
|
||||
}
|
||||
|
||||
async getPublicKeys(): Promise<void> {
|
||||
this.httpWrapperService.get(`${environment.publicKeysUrl}/keys.asc`).pipe(first()).subscribe(async res => {
|
||||
this.httpWrapperService.get(`${environment.publicKeysUrl}`).pipe(first()).subscribe(async res => {
|
||||
await this.mutableKeyStore.importPublicKey(res.body);
|
||||
}, error => {
|
||||
this.loggingService.sendErrorLevelMessage('There was an error!', this, {error});
|
||||
this.loggingService.sendErrorLevelMessage('There was an error fetching public keys!', this, {error});
|
||||
});
|
||||
if (this.privateKey !== undefined) {
|
||||
await this.mutableKeyStore.importPrivateKey(this.privateKey);
|
||||
|
@ -21,7 +21,8 @@ export class BlockSyncService {
|
||||
private loggingService: LoggingService
|
||||
) { }
|
||||
|
||||
blockSync(): any {
|
||||
blockSync(address: string = null, offset: number = 0, limit: number = 100): any {
|
||||
this.transactionService.resetTransactionsList();
|
||||
const settings = new Settings(this.scan);
|
||||
const provider = environment.web3Provider;
|
||||
const readyStateElements = { network: 2 };
|
||||
@ -40,13 +41,13 @@ export class BlockSyncService {
|
||||
};
|
||||
settings.registry.onload = (addressReturned: number): void => {
|
||||
this.loggingService.sendInfoLevelMessage(`Loaded network contracts ${addressReturned}`);
|
||||
this.readyStateProcessor(settings, readyStateElements.network);
|
||||
this.readyStateProcessor(settings, readyStateElements.network, address, offset, limit);
|
||||
};
|
||||
|
||||
settings.registry.load();
|
||||
}
|
||||
|
||||
readyStateProcessor(settings, bit): void {
|
||||
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');
|
||||
@ -56,7 +57,15 @@ export class BlockSyncService {
|
||||
wHeadSync.postMessage({
|
||||
w3_provider: settings.w3.provider,
|
||||
});
|
||||
this.fetcher(settings);
|
||||
if (address === null) {
|
||||
this.transactionService.getAllTransactions(offset, limit).pipe(first()).subscribe(res => {
|
||||
this.fetcher(settings, res.body);
|
||||
});
|
||||
} else {
|
||||
this.transactionService.getAddressTransactions(address, offset, limit).pipe(first()).subscribe(res => {
|
||||
this.fetcher(settings, res.body);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -93,17 +102,15 @@ export class BlockSyncService {
|
||||
});
|
||||
}
|
||||
|
||||
fetcher(settings: any, offset: number = 0, limit: number = 100): void {
|
||||
this.transactionService.getAllTransactions(offset, limit).pipe(first()).subscribe(res => {
|
||||
const blockFilterBinstr = window.atob(res.body.block_filter);
|
||||
const bOne = new Uint8Array(blockFilterBinstr.length);
|
||||
bOne.map((e, i, v) => v[i] = blockFilterBinstr.charCodeAt(i));
|
||||
fetcher(settings: Settings, transactionsInfo: any): void {
|
||||
const blockFilterBinstr = window.atob(transactionsInfo.block_filter);
|
||||
const bOne = new Uint8Array(blockFilterBinstr.length);
|
||||
bOne.map((e, i, v) => v[i] = blockFilterBinstr.charCodeAt(i));
|
||||
|
||||
const blocktxFilterBinstr = window.atob(res.body.blocktx_filter);
|
||||
const bTwo = new Uint8Array(blocktxFilterBinstr.length);
|
||||
bTwo.map((e, i, v) => v[i] = blocktxFilterBinstr.charCodeAt(i));
|
||||
const blocktxFilterBinstr = window.atob(transactionsInfo.blocktx_filter);
|
||||
const bTwo = new Uint8Array(blocktxFilterBinstr.length);
|
||||
bTwo.map((e, i, v) => v[i] = blocktxFilterBinstr.charCodeAt(i));
|
||||
|
||||
settings.scanFilter(settings, res.body.low, res.body.high, bOne, bTwo, res.body.filter_rounds);
|
||||
});
|
||||
settings.scanFilter(settings, transactionsInfo.low, transactionsInfo.high, bOne, bTwo, transactionsInfo.filter_rounds);
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,7 @@ export class HttpWrapperService {
|
||||
return Observable.create((observer: any) => {
|
||||
const requestBeginTime = moment();
|
||||
this.http.request(new HttpRequest(method, url, body, options)).subscribe((response) => {
|
||||
this.loggingService.sendInfoLevelMessage(response);
|
||||
this.logTime(requestBeginTime, `${url}`, method);
|
||||
observer.next(response);
|
||||
observer.complete();
|
||||
|
@ -6,3 +6,4 @@ export * from '@app/_services/block-sync.service';
|
||||
export * from '@app/_services/location.service';
|
||||
export * from '@app/_services/logging.service';
|
||||
export * from '@app/_services/http-wrapper.service';
|
||||
export * from '@app/_services/error-dialog.service';
|
||||
|
@ -1,10 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {environment} from '@src/environments/environment';
|
||||
import {BehaviorSubject, Observable} from 'rxjs';
|
||||
import {HttpGetter, Registry, TokenRegistry} from '@app/_helpers';
|
||||
import {HttpGetter} from '@app/_helpers';
|
||||
import {CICRegistry} from 'cic-client';
|
||||
import Web3 from 'web3';
|
||||
import {HttpWrapperService} from '@app/_services/http-wrapper.service';
|
||||
import {Registry, TokenRegistry} from '@app/_eth';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
|
@ -11,10 +11,10 @@ import {Tx} from '@src/assets/js/ethtx/dist';
|
||||
import {toValue} from '@src/assets/js/ethtx/dist/tx';
|
||||
import * as secp256k1 from 'secp256k1';
|
||||
import {AuthService} from '@app/_services/auth.service';
|
||||
import {Registry} from '@app/_helpers';
|
||||
import {defaultAccount} from '@app/_models';
|
||||
import {LoggingService} from '@app/_services/logging.service';
|
||||
import {HttpWrapperService} from '@app/_services/http-wrapper.service';
|
||||
import {Registry} from '@app/_eth';
|
||||
const Web3 = require('web3');
|
||||
const vCard = require('vcard-parser');
|
||||
|
||||
@ -45,22 +45,22 @@ export class TransactionService {
|
||||
}
|
||||
|
||||
async setTransaction(transaction, cacheSize: number): Promise<void> {
|
||||
if (this.transactions.find(cachedTx => cachedTx.tx.txHash === transaction.tx.txHash)) { return; }
|
||||
transaction.value = Number(transaction.value);
|
||||
transaction.type = 'transaction';
|
||||
if (this.transactions.find(cachedTx => cachedTx.tx.txHash === transaction.tx.txHash)) { return; }
|
||||
try {
|
||||
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.from)).pipe(first()).subscribe(async (res) => {
|
||||
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.from)).pipe(first()).subscribe((res) => {
|
||||
transaction.sender = this.getAccountInfo(res.body);
|
||||
}, error => {
|
||||
transaction.sender = defaultAccount;
|
||||
});
|
||||
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.to)).pipe(first()).subscribe(async (res) => {
|
||||
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.to)).pipe(first()).subscribe((res) => {
|
||||
transaction.recipient = this.getAccountInfo(res.body);
|
||||
}, error => {
|
||||
transaction.recipient = defaultAccount;
|
||||
});
|
||||
} finally {
|
||||
await this.addTransaction(transaction, cacheSize);
|
||||
this.addTransaction(transaction, cacheSize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,17 +70,17 @@ export class TransactionService {
|
||||
conversion.fromValue = Number(conversion.fromValue);
|
||||
conversion.toValue = Number(conversion.toValue);
|
||||
try {
|
||||
this.userService.getAccountDetailsFromMeta(await User.toKey(conversion.trader)).pipe(first()).subscribe(async (res) => {
|
||||
this.userService.getAccountDetailsFromMeta(await User.toKey(conversion.trader)).pipe(first()).subscribe((res) => {
|
||||
conversion.sender = conversion.recipient = this.getAccountInfo(res.body);
|
||||
}, error => {
|
||||
conversion.sender = conversion.recipient = defaultAccount;
|
||||
});
|
||||
} finally {
|
||||
await this.addTransaction(conversion, cacheSize);
|
||||
this.addTransaction(conversion, cacheSize);
|
||||
}
|
||||
}
|
||||
|
||||
async addTransaction(transaction, cacheSize: number): Promise<void> {
|
||||
addTransaction(transaction, cacheSize: number): void {
|
||||
this.transactions.unshift(transaction);
|
||||
if (this.transactions.length > cacheSize) {
|
||||
this.transactions.length = cacheSize;
|
||||
@ -88,6 +88,11 @@ export class TransactionService {
|
||||
this.transactionList.next(this.transactions);
|
||||
}
|
||||
|
||||
resetTransactionsList(): void {
|
||||
this.transactions = [];
|
||||
this.transactionList.next(this.transactions);
|
||||
}
|
||||
|
||||
getAccountInfo(account: string): any {
|
||||
let accountInfo = Envelope.fromJSON(JSON.stringify(account)).unwrap().m.data;
|
||||
accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));
|
||||
|
@ -3,11 +3,13 @@ import {BehaviorSubject, Observable} from 'rxjs';
|
||||
import {HttpClient, HttpHeaders, HttpParams} from '@angular/common/http';
|
||||
import {environment} from '@src/environments/environment';
|
||||
import {first} from 'rxjs/operators';
|
||||
import {AccountIndex, MutableKeyStore, MutablePgpKeyStore, PGPSigner, Registry, Signer} from '@app/_helpers';
|
||||
import {ArgPair, Envelope, Syncable, User} from 'cic-client-meta';
|
||||
import {MetaResponse} from '@app/_models';
|
||||
import {LoggingService} from '@app/_services/logging.service';
|
||||
import {HttpWrapperService} from '@app/_services/http-wrapper.service';
|
||||
import {TokenService} from '@app/_services/token.service';
|
||||
import {AccountIndex, Registry} from '@app/_eth';
|
||||
import {MutableKeyStore, MutablePgpKeyStore, PGPSigner, Signer} from '@app/_pgp';
|
||||
const vCard = require('vcard-parser');
|
||||
|
||||
@Injectable({
|
||||
@ -35,7 +37,8 @@ export class UserService {
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private httpWrapperService: HttpWrapperService,
|
||||
private loggingService: LoggingService
|
||||
private loggingService: LoggingService,
|
||||
private tokenService: TokenService
|
||||
) {
|
||||
}
|
||||
|
||||
@ -145,7 +148,7 @@ export class UserService {
|
||||
}
|
||||
|
||||
getAccountDetailsFromMeta(userKey: string): Observable<any> {
|
||||
return this.httpWrapperService.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers });
|
||||
return this.http.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers });
|
||||
}
|
||||
|
||||
getUser(userKey: string): any {
|
||||
@ -169,16 +172,18 @@ export class UserService {
|
||||
});
|
||||
}
|
||||
|
||||
async loadAccounts(limit: number, offset: number = 0): Promise<void> {
|
||||
async loadAccounts(limit: number = 100, offset: number = 0): Promise<void> {
|
||||
this.resetAccountsList();
|
||||
const accountIndexAddress = await this.registry.addressOf('AccountRegistry');
|
||||
const accountIndexQuery = new AccountIndex(accountIndexAddress);
|
||||
const accountAddresses = await accountIndexQuery.last(await accountIndexQuery.totalAccounts());
|
||||
this.loggingService.sendInfoLevelMessage(accountAddresses);
|
||||
for (const accountAddress of accountAddresses.slice(offset, offset + limit)) {
|
||||
this.getAccountDetailsFromMeta(await User.toKey(accountAddress)).pipe(first()).subscribe(res => {
|
||||
this.getAccountDetailsFromMeta(await User.toKey(accountAddress)).pipe(first()).subscribe(async res => {
|
||||
const account = Envelope.fromJSON(JSON.stringify(res)).unwrap();
|
||||
this.accountsMeta.push(account);
|
||||
const accountInfo = account.m.data;
|
||||
accountInfo.balance = await this.tokenService.getTokenBalance(accountInfo.identities.evm['bloxberg:8996'][0]);
|
||||
accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));
|
||||
this.accounts.unshift(accountInfo);
|
||||
if (this.accounts.length > limit) {
|
||||
|
@ -17,8 +17,8 @@
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Private Key</mat-label>
|
||||
<textarea matInput style="height: 30rem" name="privateKeyAsc" id="privateKeyAsc" formControlName="key"
|
||||
placeholder="Enter your private key..." [errorStateMatcher]="matcher"></textarea>
|
||||
<textarea matInput style="height: 30rem" formControlName="key" placeholder="Enter your private key..."
|
||||
[errorStateMatcher]="matcher"></textarea>
|
||||
<div *ngIf="submitted && keyFormStub.key.errors" class="invalid-feedback">
|
||||
<mat-error *ngIf="keyFormStub.key.errors.required">Private Key is required.</mat-error>
|
||||
</div>
|
||||
@ -34,23 +34,10 @@
|
||||
<div id="two" style="display: none" class="card-body p-4 align-items-center">
|
||||
|
||||
<div class="text-center w-75 m-auto">
|
||||
<h4 class="text-dark-50 text-center font-weight-bold">Enter Passphrase</h4>
|
||||
<h4 id="state" class="text-dark-50 text-center font-weight-bold"></h4>
|
||||
<button mat-raised-button matRipple color="primary" type="submit" (click)="login()"> Login </button>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="stateForm" (ngSubmit)="login()">
|
||||
|
||||
<mat-form-field appearance="outline" class="full-width">
|
||||
<mat-label>Login State</mat-label>
|
||||
<input matInput name="state" id="state" formControlName="state" readonly disabled>
|
||||
</mat-form-field>
|
||||
|
||||
<div class="form-group mb-0 text-center">
|
||||
<button mat-raised-button matRipple color="primary" type="submit">
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 text-center">
|
||||
<p class="text-muted">Change private key? <a (click)="switchWindows()" class="text-muted ml-1"><b>Enter private key</b></a></p>
|
||||
|
@ -12,7 +12,6 @@ import {Router} from '@angular/router';
|
||||
})
|
||||
export class AuthComponent implements OnInit {
|
||||
keyForm: FormGroup;
|
||||
stateForm: FormGroup;
|
||||
submitted: boolean = false;
|
||||
loading: boolean = false;
|
||||
matcher = new CustomErrorStateMatcher();
|
||||
@ -27,14 +26,11 @@ export class AuthComponent implements OnInit {
|
||||
this.keyForm = this.formBuilder.group({
|
||||
key: ['', Validators.required],
|
||||
});
|
||||
this.stateForm = this.formBuilder.group({
|
||||
state: '',
|
||||
});
|
||||
if (this.authService.privateKey !== undefined ) {
|
||||
this.authService.setKey(this.authService.privateKey).then(r => {
|
||||
if (this.authService.sessionToken !== undefined) {
|
||||
this.authService.setState(
|
||||
'click to perform login ' + this.authService.sessionLoginCount + ' with token ' + this.authService.sessionToken);
|
||||
'Click button to perform login ' + this.authService.sessionLoginCount + ' with token ' + this.authService.sessionToken);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -54,6 +50,7 @@ export class AuthComponent implements OnInit {
|
||||
|
||||
login(): void {
|
||||
const loginStatus = this.authService.login();
|
||||
console.log(loginStatus);
|
||||
if (loginStatus) {
|
||||
this.router.navigate(['/home']);
|
||||
}
|
||||
|
@ -3,9 +3,6 @@
|
||||
<p>
|
||||
Message: {{ data.message }}
|
||||
</p>
|
||||
<p>
|
||||
Reason: {{ data.reason }}
|
||||
</p>
|
||||
<p>
|
||||
Status: {{ data.status }}
|
||||
</p>
|
||||
|
@ -9,6 +9,6 @@ import {MAT_DIALOG_DATA} from '@angular/material/dialog';
|
||||
})
|
||||
export class ErrorDialogComponent {
|
||||
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public data: string) { }
|
||||
constructor(@Inject(MAT_DIALOG_DATA) public data: any) { }
|
||||
|
||||
}
|
||||
|
@ -6,9 +6,9 @@ export const environment = {
|
||||
level: NgxLoggerLevel.OFF,
|
||||
serverLogLevel: NgxLoggerLevel.ERROR,
|
||||
loggingUrl: 'http://localhost:8000',
|
||||
cicAuthUrl: 'https://meta.dev.grassrootseconomics.net',
|
||||
cicAuthUrl: 'https://meta.dev.grassrootseconomics.net:80',
|
||||
cicMetaUrl: 'http://localhost:63380',
|
||||
publicKeysUrl: 'http://localhost:8000',
|
||||
publicKeysUrl: 'http://localhost:8000/keys.asc',
|
||||
cicCacheUrl: 'http://localhost:63313',
|
||||
cicScriptsUrl: 'http://localhost:9999',
|
||||
web3Provider: 'ws://localhost:63546',
|
||||
|
@ -10,9 +10,9 @@ export const environment = {
|
||||
level: NgxLoggerLevel.TRACE,
|
||||
serverLogLevel: NgxLoggerLevel.ERROR,
|
||||
loggingUrl: 'http://localhost:8000',
|
||||
cicAuthUrl: 'https://meta.dev.grassrootseconomics.net',
|
||||
cicAuthUrl: 'https://meta.dev.grassrootseconomics.net:80',
|
||||
cicMetaUrl: 'http://localhost:63380',
|
||||
publicKeysUrl: 'http://localhost:8000',
|
||||
publicKeysUrl: 'http://localhost:8000/keys.asc',
|
||||
cicCacheUrl: 'http://localhost:63313',
|
||||
cicScriptsUrl: 'http://localhost:9999',
|
||||
web3Provider: 'ws://localhost:63546',
|
||||
|
Loading…
Reference in New Issue
Block a user