Add fetching of transaction participants from cic-meta.

Add token registry to query tokens.
This commit is contained in:
Spencer Ofwiti 2021-03-10 12:47:01 +03:00
parent 7447bf2499
commit 32ab27730b
23 changed files with 262 additions and 125 deletions

View File

@ -22,7 +22,7 @@ export class AccountIndex {
} }
public async totalAccounts(): Promise<number> { public async totalAccounts(): Promise<number> {
return this.contract.methods.count().call(); return await this.contract.methods.count().call();
} }
public async haveAccount(address: string): Promise<boolean> { public async haveAccount(address: string): Promise<boolean> {

View File

@ -8,3 +8,4 @@ export * from '@app/_helpers/accountIndex';
export * from '@app/_helpers/http-getter'; export * from '@app/_helpers/http-getter';
export * from '@app/_helpers/pgp-signer'; export * from '@app/_helpers/pgp-signer';
export * from '@app/_helpers/registry'; export * from '@app/_helpers/registry';
export * from '@app/_helpers/token-registry';

View File

@ -1,7 +1,8 @@
import { Registry } from './registry'; import { Registry } from '@app/_helpers/registry';
import {environment} from '@src/environments/environment';
describe('Registry', () => { describe('Registry', () => {
it('should create an instance', () => { it('should create an instance', () => {
expect(new Registry()).toBeTruthy(); expect(new Registry(environment.registryAddress)).toBeTruthy();
}); });
}); });

View File

@ -0,0 +1,8 @@
import { TokenRegistry } from '@app/_helpers/token-registry';
import {environment} from '@src/environments/environment';
describe('TokenRegistry', () => {
it('should create an instance', () => {
expect(new TokenRegistry(environment.registryAddress)).toBeTruthy();
});
});

View File

@ -0,0 +1,36 @@
// @ts-ignore
import * as registryClient from '@src/assets/js/block-sync/data/RegistryClient.json';
import Web3 from 'web3';
import {environment} from '@src/environments/environment';
const web3 = new Web3(environment.web3Provider);
const abi = registryClient.default;
export class TokenRegistry {
contractAddress: string;
signerAddress: string;
contract: any;
constructor(contractAddress: string, signerAddress?: string) {
this.contractAddress = contractAddress;
this.contract = new web3.eth.Contract(abi, this.contractAddress);
if (signerAddress) {
this.signerAddress = signerAddress;
} else {
this.signerAddress = web3.eth.accounts[0];
}
}
public async totalTokens(): Promise<number> {
return await this.contract.methods.registryCount().call();
}
public async entry(serial: number): Promise<string> {
return await this.contract.methods.entry(serial).call();
}
public async addressOf(identifier: string): Promise<string> {
const id = '0x' + web3.utils.padRight(new Buffer(identifier).toString('hex'), 64);
return await this.contract.methods.addressOf(id).call();
}
}

View File

@ -52,3 +52,40 @@ export interface MetaResponse {
id: string; id: string;
m: Meta; m: Meta;
} }
export const defaultAccount: AccountDetails = {
date_registered: Date.now(),
gender: 'other',
identities: {
evm: {
'bloxberg:8996': [''],
'oldchain:1': [''],
},
latitude: 0,
longitude: 0,
},
location: {
area_name: 'Kilifi',
},
products: [],
vcard: {
email: [{
value: '',
}],
fn: [{
value: 'GE',
}],
n: [{
value: ['GE'],
}],
tel: [{
meta: {
TYP: [],
},
value: '',
}],
version: [{
value: '3.0',
}],
},
};

View File

@ -3,11 +3,18 @@ import {HttpClient} from '@angular/common/http';
import {environment} from '@src/environments/environment'; import {environment} from '@src/environments/environment';
import {first} from 'rxjs/operators'; import {first} from 'rxjs/operators';
import {BehaviorSubject} from 'rxjs'; import {BehaviorSubject} from 'rxjs';
import {HttpGetter, Registry, TokenRegistry} from '@app/_helpers';
import {CICRegistry} from 'cic-client';
import Web3 from 'web3';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class TokenService { export class TokenService {
web3 = new Web3(environment.web3Provider);
fileGetter = new HttpGetter();
registry = new Registry(environment.registryAddress);
cicRegistry = new CICRegistry(this.web3, environment.registryAddress, this.fileGetter, ['../../assets/js/block-sync/data']);
tokens: any = ''; tokens: any = '';
private tokensList = new BehaviorSubject<any>(this.tokens); private tokensList = new BehaviorSubject<any>(this.tokens);
tokensSubject = this.tokensList.asObservable(); tokensSubject = this.tokensList.asObservable();
@ -16,11 +23,19 @@ export class TokenService {
private http: HttpClient private http: HttpClient
) { } ) { }
getTokens(): any { async getTokens(): Promise<any> {
this.http.get(`${environment.cicCacheUrl}/tokens`).pipe(first()).subscribe(tokens => this.tokensList.next(tokens)); const tokenRegistryQuery = new TokenRegistry(await this.registry.addressOf('TokenRegistry'));
const count = await tokenRegistryQuery.totalTokens();
return Array.from({length: count}, async (v, i) => await tokenRegistryQuery.entry(i));
} }
getTokenBySymbol(symbol: string): any { getTokenBySymbol(symbol: string): any {
return this.http.get(`${environment.cicCacheUrl}/tokens/${symbol}`); return this.http.get(`${environment.cicCacheUrl}/tokens/${symbol}`);
} }
async getTokenBalance(address: string): Promise<number> {
const tokenRegistryQuery = new TokenRegistry(await this.registry.addressOf('TokenRegistry'));
const sarafuToken = await this.cicRegistry.addToken(await tokenRegistryQuery.entry(0));
return await sarafuToken.methods.balanceOf(address).call();
}
} }

View File

@ -13,6 +13,7 @@ import {toValue} from '@src/assets/js/ethtx/dist/tx';
import * as secp256k1 from 'secp256k1'; import * as secp256k1 from 'secp256k1';
import {AuthService} from '@app/_services/auth.service'; import {AuthService} from '@app/_services/auth.service';
import {Registry} from '@app/_helpers'; import {Registry} from '@app/_helpers';
import {defaultAccount} from '@app/_models';
const Web3 = require('web3'); const Web3 = require('web3');
const vCard = require('vcard-parser'); const vCard = require('vcard-parser');
@ -48,21 +49,40 @@ export class TransactionService {
} }
async setTransaction(transaction, cacheSize: number): Promise<void> { async setTransaction(transaction, cacheSize: number): Promise<void> {
const cachedTransaction = this.transactions.find(cachedTx => cachedTx.tx.txHash === transaction.tx.txHash); transaction.value = Number(transaction.value);
if (cachedTransaction) { return; }
transaction.type = 'transaction'; transaction.type = 'transaction';
transaction.sender = await this.getUser(transaction.from); if (this.transactions.find(cachedTx => cachedTx.tx.txHash === transaction.tx.txHash)) { return; }
transaction.recipient = await this.getUser(transaction.to); try {
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.from)).pipe(first()).subscribe(async (res) => {
transaction.sender = this.getAccountInfo(res);
}, error => {
transaction.sender = defaultAccount;
});
this.userService.getAccountDetailsFromMeta(await User.toKey(transaction.to)).pipe(first()).subscribe(async (res) => {
transaction.recipient = this.getAccountInfo(res);
}, error => {
transaction.recipient = defaultAccount;
});
} finally {
await this.addTransaction(transaction, cacheSize); await this.addTransaction(transaction, cacheSize);
} }
}
async setConversion(conversion, cacheSize): Promise<void> { async setConversion(conversion, cacheSize): Promise<void> {
const cachedConversion = this.transactions.find(cachedTx => cachedTx.tx.txHash === conversion.tx.txHash); if (this.transactions.find(cachedTx => cachedTx.tx.txHash === conversion.tx.txHash)) { return; }
if (cachedConversion) { return; }
conversion.type = 'conversion'; conversion.type = 'conversion';
conversion.sender = conversion.recipient = await this.getUser(conversion.trader); conversion.fromValue = Number(conversion.fromValue);
conversion.toValue = Number(conversion.toValue);
try {
this.userService.getAccountDetailsFromMeta(await User.toKey(conversion.trader)).pipe(first()).subscribe(async (res) => {
conversion.sender = conversion.recipient = this.getAccountInfo(res);
}, error => {
conversion.sender = conversion.recipient = defaultAccount;
});
} finally {
await this.addTransaction(conversion, cacheSize); await this.addTransaction(conversion, cacheSize);
} }
}
async addTransaction(transaction, cacheSize: number): Promise<void> { async addTransaction(transaction, cacheSize: number): Promise<void> {
this.transactions.unshift(transaction); this.transactions.unshift(transaction);
@ -72,14 +92,10 @@ export class TransactionService {
this.transactionList.next(this.transactions); this.transactionList.next(this.transactions);
} }
async getUser(address: string): Promise<any> { getAccountInfo(account: string): any {
return this.userService.getAccountDetailsFromMeta(await User.toKey(address)).pipe(first()).subscribe(res => { let accountInfo = Envelope.fromJSON(JSON.stringify(account)).unwrap().m.data;
const account = Envelope.fromJSON(JSON.stringify(res)).unwrap();
const accountInfo = account.m.data;
accountInfo.vcard = vCard.parse(atob(accountInfo.vcard)); accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));
this.userInfo = accountInfo;
return accountInfo; return accountInfo;
});
} }
async transferRequest(tokenAddress: string, senderAddress: string, recipientAddress: string, value: number): Promise<any> { async transferRequest(tokenAddress: string, senderAddress: string, recipientAddress: string, value: number): Promise<any> {

View File

@ -134,7 +134,7 @@ export class UserService {
} }
getUser(userKey: string): any { getUser(userKey: string): any {
this.http.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers }).pipe(first()).subscribe(async res => { return this.http.get(`${environment.cicMetaUrl}/${userKey}`, { headers: this.headers }).pipe(first()).subscribe(async res => {
return Envelope.fromJSON(JSON.stringify(res)).unwrap(); return Envelope.fromJSON(JSON.stringify(res)).unwrap();
}); });
} }
@ -154,19 +154,27 @@ export class UserService {
} }
async loadAccounts(limit: number, offset: number = 0): Promise<void> { async loadAccounts(limit: number, offset: number = 0): Promise<void> {
this.resetAccountsList();
const accountIndexAddress = await this.registry.addressOf('AccountRegistry'); const accountIndexAddress = await this.registry.addressOf('AccountRegistry');
const accountIndexQuery = new AccountIndex(accountIndexAddress); const accountIndexQuery = new AccountIndex(accountIndexAddress);
const accountAddresses = await accountIndexQuery.last(await accountIndexQuery.totalAccounts()); const accountAddresses = await accountIndexQuery.last(await accountIndexQuery.totalAccounts());
console.log(accountAddresses);
for (const accountAddress of accountAddresses.slice(offset, offset + limit)) { 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(res => {
const account = Envelope.fromJSON(JSON.stringify(res)).unwrap(); const account = Envelope.fromJSON(JSON.stringify(res)).unwrap();
this.accountsMeta.push(account); this.accountsMeta.push(account);
const accountInfo = account.m.data; const accountInfo = account.m.data;
accountInfo.vcard = vCard.parse(atob(accountInfo.vcard)); accountInfo.vcard = vCard.parse(atob(accountInfo.vcard));
this.accounts.push(accountInfo); this.accounts.unshift(accountInfo);
if (this.accounts.length > limit) {
this.accounts.length = limit;
}
this.accountsList.next(this.accounts); this.accountsList.next(this.accounts);
}); });
} }
} }
resetAccountsList(): void {
this.accounts = [];
this.accountsList.next(this.accounts);
}
} }

View File

@ -1,5 +1,5 @@
import {Component, HostListener} from '@angular/core'; import {Component, HostListener} from '@angular/core';
import {TransactionService} from '@app/_services'; import {TokenService, TransactionService} from '@app/_services';
import {AuthService} from '@app/_services'; import {AuthService} from '@app/_services';
@Component({ @Component({
@ -15,9 +15,11 @@ export class AppComponent {
constructor( constructor(
private authService: AuthService, private authService: AuthService,
private tokenService: TokenService,
private transactionService: TransactionService, private transactionService: TransactionService,
) { ) {
this.authService.mutableKeyStore.loadKeyring().then(r => this.authService.getPublicKeys().then()); this.authService.mutableKeyStore.loadKeyring().then(r => this.authService.getPublicKeys().then());
this.tokenService.getTokens().then(async r => console.log('Tokens:', await r));
this.mediaQuery.addListener(this.onResize); this.mediaQuery.addListener(this.onResize);
this.onResize(this.mediaQuery); this.onResize(this.mediaQuery);
} }

View File

@ -17,18 +17,6 @@
<!-- <li *ngIf="account" class="breadcrumb-item active" aria-current="page">{{account?.fn[0].value}}</li>--> <!-- <li *ngIf="account" class="breadcrumb-item active" aria-current="page">{{account?.fn[0].value}}</li>-->
</ol> </ol>
</nav> </nav>
<div class="card mb-3">
<div class="row card-body">
<h3>
<strong> {{account?.fn[0].value}} </strong>
</h3>
<span class="ml-auto"><strong>Balance:</strong> {{account?.balance}} RCU</span>
<span class="ml-2"><strong>Created:</strong> {{account?.date_registered | date}}</span>
<!-- <span class="ml-2"><strong>Address:</strong><a href="{{bloxbergLink}}" target="_blank"> {{account?.identities.evm['bloxberg:8996']}} </a></span>-->
</div>
</div>
<app-disbursement *ngIf="isDisbursing" (cancelDisbursmentEvent)="addTransfer()" [account]="account">
</app-disbursement>
<div *ngIf="!account" class="text-center"> <div *ngIf="!account" class="text-center">
<div class="spinner-grow text-primary m-1" role="status" style="width: 3rem; height: 3rem;"> <div class="spinner-grow text-primary m-1" role="status" style="width: 3rem; height: 3rem;">
<span class="sr-only">Loading...</span> <span class="sr-only">Loading...</span>
@ -41,6 +29,18 @@
</div> </div>
</div> </div>
<div *ngIf="account" class="card mt-3 mb-3"> <div *ngIf="account" class="card mt-3 mb-3">
<div class="card mb-3">
<div class="row card-body">
<h3>
<strong> {{account?.vcard?.fn[0].value}} </strong>
</h3>
<span class="ml-auto"><strong>Balance:</strong> {{accountBalance}} RCU</span>
<span class="ml-2"><strong>Created:</strong> {{account?.date_registered | date}}</span>
<span class="ml-2"><strong>Address:</strong><a href="{{bloxbergLink}}" target="_blank"> {{account?.identities.evm['bloxberg:8996']}} </a></span>
</div>
</div>
<app-disbursement *ngIf="isDisbursing" (cancelDisbursmentEvent)="addTransfer()" [account]="account">
</app-disbursement>
<mat-card-title class="card-header"> <mat-card-title class="card-header">
<div class="row"> <div class="row">
DETAILS DETAILS

View File

@ -3,7 +3,7 @@ import {MatTableDataSource} from '@angular/material/table';
import {SelectionModel} from '@angular/cdk/collections'; import {SelectionModel} from '@angular/cdk/collections';
import {MatPaginator} from '@angular/material/paginator'; import {MatPaginator} from '@angular/material/paginator';
import {MatSort} from '@angular/material/sort'; import {MatSort} from '@angular/material/sort';
import {LocationService, TransactionService, UserService} from '@app/_services'; import {LocationService, TokenService, TransactionService, UserService} from '@app/_services';
import {ActivatedRoute, Params, Router} from '@angular/router'; import {ActivatedRoute, Params, Router} from '@angular/router';
import {first} from 'rxjs/operators'; import {first} from 'rxjs/operators';
import {FormBuilder, FormGroup, Validators} from '@angular/forms'; import {FormBuilder, FormGroup, Validators} from '@angular/forms';
@ -34,6 +34,7 @@ export class AccountDetailsComponent implements OnInit {
accountInfoForm: FormGroup; accountInfoForm: FormGroup;
account: any; account: any;
accountBalance: number;
metaAccount: any; metaAccount: any;
accounts: any[] = []; accounts: any[] = [];
accountsType = 'all'; accountsType = 'all';
@ -57,7 +58,8 @@ export class AccountDetailsComponent implements OnInit {
private transactionService: TransactionService, private transactionService: TransactionService,
private userService: UserService, private userService: UserService,
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router private router: Router,
private tokenService: TokenService
) { ) {
this.accountInfoForm = this.formBuilder.group({ this.accountInfoForm = this.formBuilder.group({
status: ['', Validators.required], status: ['', Validators.required],
@ -79,6 +81,7 @@ export class AccountDetailsComponent implements OnInit {
this.userService.getAccountDetailsFromMeta(await User.toKey(params.get('id'))).pipe(first()).subscribe(res => { this.userService.getAccountDetailsFromMeta(await User.toKey(params.get('id'))).pipe(first()).subscribe(res => {
this.metaAccount = Envelope.fromJSON(JSON.stringify(res)).unwrap(); this.metaAccount = Envelope.fromJSON(JSON.stringify(res)).unwrap();
this.account = this.metaAccount.m.data; this.account = this.metaAccount.m.data;
this.tokenService.getTokenBalance(this.account.identities.evm['bloxberg:8996'][0]).then(r => this.accountBalance = r);
this.account.vcard = vCard.parse(atob(this.account.vcard)); this.account.vcard = vCard.parse(atob(this.account.vcard));
console.log(this.account); console.log(this.account);
this.accountInfoForm.patchValue({ this.accountInfoForm.patchValue({

View File

@ -14,27 +14,29 @@
<li class="list-group-item"> <li class="list-group-item">
<span>Sender: {{transaction.sender?.vcard.fn[0].value}}</span><br><br> <span>Sender: {{transaction.sender?.vcard.fn[0].value}}</span><br><br>
<span>Sender Address: {{transaction.from}}</span><br><br> <span>Sender Address: {{transaction.from}}</span><br><br>
<button mat-raised-button color="primary" class="btn btn-outline-info" routerLink="/accounts/1">View Sender</button> <button mat-raised-button color="primary" class="btn btn-outline-info" (click)="viewSender()">View Sender</button>
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<span>Recipient: {{transaction.recipient?.vcard.fn[0].value}}</span><br><br> <span>Recipient: {{transaction.recipient?.vcard.fn[0].value}}</span><br><br>
<span>Recipient Address: {{transaction.to}}</span><br><br> <span>Recipient Address: {{transaction.to}}</span><br><br>
<button mat-raised-button color="primary" class="btn btn-outline-info" routerLink="/accounts/1">View Recipient</button> <button mat-raised-button color="primary" class="btn btn-outline-info" (click)="viewRecipient()">View Recipient</button>
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<span>Amount: {{transaction.token.symbol + ' ' + transaction.value}}</span> <span>Amount: SRF {{transaction.value | tokenRatio}}</span>
</li> </li>
</ul> </ul>
<h4 class="mt-2">Token: </h4> <h4 class="mt-2">Token: </h4>
<ul class="list-group list-group-flush"> <ul class="list-group list-group-flush">
<li class="list-group-item"> <li class="list-group-item">
<span>Address: {{transaction.token.address}}</span> <span>Address: {{transaction.token._address}}</span>
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<span>Name: {{transaction.token.name}}</span> <!-- <span>Name: {{transaction.token.name}}</span>-->
<span>Name: Sarafu Token</span>
</li> </li>
<li class="list-group-item"> <li class="list-group-item">
<span>Symbol: {{transaction.token.symbol}}</span> <!-- <span>Symbol: {{transaction.token.symbol}}</span>-->
<span>Symbol: SRF</span>
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -1,4 +1,5 @@
import {Component, Input, OnInit} from '@angular/core'; import {Component, Input, OnInit} from '@angular/core';
import {Router} from '@angular/router';
@Component({ @Component({
selector: 'app-transaction-details', selector: 'app-transaction-details',
@ -8,9 +9,16 @@ import {Component, Input, OnInit} from '@angular/core';
export class TransactionDetailsComponent implements OnInit { export class TransactionDetailsComponent implements OnInit {
@Input() transaction; @Input() transaction;
constructor() { } constructor(private router: Router) { }
ngOnInit(): void { ngOnInit(): void {
} }
viewSender(): void {
this.router.navigateByUrl(`/accounts/${this.transaction.from}`).then();
}
viewRecipient(): void {
this.router.navigateByUrl(`/accounts/${this.transaction.to}`).then();
}
} }

View File

@ -56,82 +56,75 @@
<mat-icon matSuffix>search</mat-icon> <mat-icon matSuffix>search</mat-icon>
</mat-form-field> </mat-form-field>
<mat-table class="mat-elevation-z10" [dataSource]="transactionDataSource" matSort matSortActive="created" <table mat-table class="mat-elevation-z10" [dataSource]="transactionDataSource" matSort matSortActive="created"
matSortDirection="desc" matSortDisableClear> matSortDirection="desc" matSortDisableClear>
<ng-container matColumnDef="view">
<mat-header-cell *matHeaderCellDef> View </mat-header-cell>
<mat-cell *matCellDef="let transaction" (click)="viewTransaction(transaction)">
<i class="fa fa-eye"></i>
</mat-cell>
</ng-container>
<ng-container matColumnDef="sender"> <ng-container matColumnDef="sender">
<mat-header-cell *matHeaderCellDef mat-sort-header> Sender </mat-header-cell> <th mat-header-cell *matHeaderCellDef mat-sort-header> Sender </th>
<mat-cell *matCellDef="let transaction"> {{transaction.sender?.vcard.fn[0].value}} </mat-cell> <td mat-cell *matCellDef="let transaction"> {{transaction?.sender?.vcard.fn[0].value}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="senderLocation"> <!-- <ng-container matColumnDef="senderLocation">-->
<mat-header-cell *matHeaderCellDef mat-sort-header> Sender Location </mat-header-cell> <!-- <mat-header-cell *matHeaderCellDef mat-sort-header> Sender Location </mat-header-cell>-->
<mat-cell *matCellDef="let transaction"> {{transaction.sender?.location.area_name}} </mat-cell> <!-- <mat-cell *matCellDef="let transaction"> {{transaction?.sender?.location.area_name}} </mat-cell>-->
</ng-container> <!-- </ng-container>-->
<ng-container matColumnDef="recipient"> <ng-container matColumnDef="recipient">
<mat-header-cell *matHeaderCellDef mat-sort-header> Recipient </mat-header-cell> <th mat-header-cell *matHeaderCellDef mat-sort-header> Recipient </th>
<mat-cell *matCellDef="let transaction"> {{transaction.recipient?.vcard.fn[0].value}} </mat-cell> <td mat-cell *matCellDef="let transaction"> {{transaction?.recipient?.vcard.fn[0].value}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="recipientLocation"> <!-- <ng-container matColumnDef="recipientLocation">-->
<mat-header-cell *matHeaderCellDef mat-sort-header> Recipient Location </mat-header-cell> <!-- <mat-header-cell *matHeaderCellDef mat-sort-header> Recipient Location </mat-header-cell>-->
<mat-cell *matCellDef="let transaction"> {{transaction.recipient?.location.area_name}} </mat-cell> <!-- <mat-cell *matCellDef="let transaction"> {{transaction?.recipient?.location.area_name}} </mat-cell>-->
</ng-container> <!-- </ng-container>-->
<ng-container matColumnDef="token"> <!-- <ng-container matColumnDef="token">-->
<mat-header-cell *matHeaderCellDef mat-sort-header> Token </mat-header-cell> <!-- <mat-header-cell *matHeaderCellDef mat-sort-header> Token </mat-header-cell>-->
<mat-cell *matCellDef="let transaction"> <!-- <mat-cell *matCellDef="let transaction">-->
<span *ngIf="transaction.type == 'transaction'">{{transaction.token.name}}</span> <!-- <span *ngIf="transaction.type == 'transaction'">{{transaction?.token.name}}</span>-->
<span *ngIf="transaction.type == 'conversion'">{{transaction.destinationToken.name}}</span> <!-- <span *ngIf="transaction.type == 'conversion'">{{transaction?.destinationToken.name}}</span>-->
</mat-cell> <!-- </mat-cell>-->
</ng-container> <!-- </ng-container>-->
<ng-container matColumnDef="value"> <ng-container matColumnDef="value">
<mat-header-cell *matHeaderCellDef mat-sort-header> Value </mat-header-cell> <th mat-header-cell *matHeaderCellDef mat-sort-header> Value </th>
<mat-cell *matCellDef="let transaction"> <td mat-cell *matCellDef="let transaction">
<span *ngIf="transaction.type == 'transaction'">{{transaction.value | tokenRatio}}</span> <span *ngIf="transaction.type == 'transaction'">{{transaction?.value | tokenRatio}}</span>
<span *ngIf="transaction.type == 'conversion'">{{transaction.toValue | tokenRatio}}</span> <span *ngIf="transaction.type == 'conversion'">{{transaction?.toValue | tokenRatio}}</span>
</mat-cell> </td>
</ng-container> </ng-container>
<ng-container matColumnDef="created"> <ng-container matColumnDef="created">
<mat-header-cell *matHeaderCellDef mat-sort-header> Created </mat-header-cell> <th mat-header-cell *matHeaderCellDef mat-sort-header> Created </th>
<mat-cell *matCellDef="let transaction"> {{transaction.tx.timestamp | date}} </mat-cell> <td mat-cell *matCellDef="let transaction"> {{transaction?.tx.timestamp | date}} </td>
</ng-container> </ng-container>
<ng-container matColumnDef="type"> <ng-container matColumnDef="type">
<mat-header-cell *matHeaderCellDef mat-sort-header> TYPE </mat-header-cell> <th mat-header-cell *matHeaderCellDef mat-sort-header> TYPE </th>
<mat-cell *matCellDef="let transaction"> <td mat-cell *matCellDef="let transaction">
<span class="badge badge-success badge-pill"> {{transaction.type}} </span> <span class="badge badge-success badge-pill"> {{transaction?.type}} </span>
</mat-cell> </td>
</ng-container> </ng-container>
<ng-container matColumnDef="select"> <!-- <ng-container matColumnDef="select">-->
<mat-header-cell *matHeaderCellDef> <!-- <mat-header-cell *matHeaderCellDef>-->
<mat-checkbox (change)="$event ? masterToggle(transactionSelection, transactionDataSource) : null" <!-- <mat-checkbox (change)="$event ? masterToggle(transactionSelection, transactionDataSource) : null"-->
[checked]="transactionSelection.hasValue() && isAllSelected(transactionSelection, transactionDataSource)" <!-- [checked]="transactionSelection.hasValue() && isAllSelected(transactionSelection, transactionDataSource)"-->
[indeterminate]="transactionSelection.hasValue() && !isAllSelected(transactionSelection, transactionDataSource)"> <!-- [indeterminate]="transactionSelection.hasValue() && !isAllSelected(transactionSelection, transactionDataSource)">-->
</mat-checkbox> <!-- </mat-checkbox>-->
</mat-header-cell> <!-- </mat-header-cell>-->
<mat-cell *matCellDef="let transaction"> <!-- <mat-cell *matCellDef="let transaction">-->
<mat-checkbox (click)="$event.stopPropagation()" <!-- <mat-checkbox (click)="$event.stopPropagation()"-->
(change)="$event ? transactionSelection.toggle(transaction) : null" <!-- (change)="$event ? transactionSelection.toggle(transaction) : null"-->
[checked]="transactionSelection.isSelected(transaction)"> <!-- [checked]="transactionSelection.isSelected(transaction)">-->
</mat-checkbox> <!-- </mat-checkbox>-->
</mat-cell> <!-- </mat-cell>-->
</ng-container> <!-- </ng-container>-->
<mat-header-row *matHeaderRowDef="transactionDisplayedColumns"></mat-header-row> <tr mat-header-row *matHeaderRowDef="transactionDisplayedColumns"></tr>
<mat-row *matRowDef="let transaction; columns: transactionDisplayedColumns" (click)="viewTransaction(transaction)"></mat-row> <tr mat-row *matRowDef="let transaction; columns: transactionDisplayedColumns;" (click)="viewTransaction(transaction)"></tr>
</mat-table> </table>
<mat-paginator [pageSize]="10" [pageSizeOptions]="[10, 20, 50, 100]" showFirstLastButtons></mat-paginator> <mat-paginator [pageSize]="10" [pageSizeOptions]="[10, 20, 50, 100]" showFirstLastButtons></mat-paginator>

View File

@ -12,7 +12,7 @@ import {MatSort} from '@angular/material/sort';
}) })
export class TransactionsComponent implements OnInit, AfterViewInit { export class TransactionsComponent implements OnInit, AfterViewInit {
transactionDataSource: MatTableDataSource<any>; transactionDataSource: MatTableDataSource<any>;
transactionDisplayedColumns = ['view', 'sender', 'senderLocation', 'recipient', 'recipientLocation', 'token', 'value', 'created', 'type', 'select']; transactionDisplayedColumns = ['sender', 'recipient', 'value', 'created', 'type'];
initialSelection = []; initialSelection = [];
allowMultiSelect = true; allowMultiSelect = true;
transactionSelection: SelectionModel<any>; transactionSelection: SelectionModel<any>;

View File

@ -16,6 +16,7 @@ import {MatButtonModule} from '@angular/material/button';
import {MatIconModule} from '@angular/material/icon'; import {MatIconModule} from '@angular/material/icon';
import {MatSelectModule} from '@angular/material/select'; import {MatSelectModule} from '@angular/material/select';
import {MatCardModule} from '@angular/material/card'; import {MatCardModule} from '@angular/material/card';
import {MatRippleModule} from '@angular/material/core';
@NgModule({ @NgModule({
@ -37,7 +38,8 @@ import {MatCardModule} from '@angular/material/card';
MatButtonModule, MatButtonModule,
MatIconModule, MatIconModule,
MatSelectModule, MatSelectModule,
MatCardModule MatCardModule,
MatRippleModule
] ]
}) })
export class TransactionsModule { } export class TransactionsModule { }

View File

@ -3,6 +3,6 @@ import {Pipe, PipeTransform} from '@angular/core';
@Pipe({name: 'tokenRatio'}) @Pipe({name: 'tokenRatio'})
export class TokenRatioPipe implements PipeTransform { export class TokenRatioPipe implements PipeTransform {
transform(value: any, ...args): any { transform(value: any, ...args): any {
return Number(value) / Math.pow(10, 18); return Number(value) / Math.pow(10, 6);
} }
} }

View File

@ -1,7 +1,7 @@
<!-- Topbar Start --> <!-- Topbar Start -->
<nav class="navbar navbar-expand-lg navbar-light bg-light sticky-top"> <nav class="navbar navbar-expand-lg navbar-light bg-light sticky-top">
<div class="container-fluid"> <div class="container-fluid">
<button type="button" id="sidebarCollapse" class="navbar-btn menutoggle" appMenuToggle> <button type="button" id="sidebarCollapse" class="navbar-btn menutoggle" aria-label="Sidebar toggle" appMenuToggle>
<span></span> <span></span>
<span></span> <span></span>
<span></span> <span></span>

View File

@ -0,0 +1 @@
[{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"addressOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"entry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"registryCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

View File

@ -1,7 +1,7 @@
export const environment = { export const environment = {
production: true, production: true,
bloxbergChainId: 8996, bloxbergChainId: 8996,
cicAuthUrl: 'http://localhost:4444', cicAuthUrl: 'http://localhost:8080',
cicMetaUrl: 'http://localhost:63380', cicMetaUrl: 'http://localhost:63380',
publicKeysUrl: 'http://localhost:8000', publicKeysUrl: 'http://localhost:8000',
cicCacheUrl: 'http://localhost:63313', cicCacheUrl: 'http://localhost:63313',

View File

@ -5,7 +5,7 @@
export const environment = { export const environment = {
production: false, production: false,
bloxbergChainId: 8996, bloxbergChainId: 8996,
cicAuthUrl: 'http://localhost:4444', cicAuthUrl: 'http://localhost:8080',
cicMetaUrl: 'http://localhost:63380', cicMetaUrl: 'http://localhost:63380',
publicKeysUrl: 'http://localhost:8000', publicKeysUrl: 'http://localhost:8000',
cicCacheUrl: 'http://localhost:63313', cicCacheUrl: 'http://localhost:63313',

View File

@ -12,7 +12,7 @@ p {
font-size: 1.1em; font-size: 1.1em;
font-weight: 300; font-weight: 300;
line-height: 1.7em; line-height: 1.7em;
color: #999; color: #000000;
} }
a, a:hover, a:focus { a, a:hover, a:focus {
@ -349,6 +349,10 @@ button {
html, body { height: 100%; } html, body { height: 100%; }
body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; }
.full-width { .full-width, table {
width: 100%; width: 100%;
} }
li.breadcrumb-item.active, footer.footer {
color: black;
}