Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WEB v2: Fee recipient UI #229

Merged
merged 6 commits into from
Jun 30, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/app/modules/core/interceptors/mock.interceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { EnvironmenterService } from '../services/environmenter.service';

export const VALIDATOR_API_PREFIX = '/v2/validator';
export const KEYMANAGER_API_PREFIX = '/eth/v1/keystores';
export const KEYMANAGER_API_VALIDATOR_PREFIX = '/eth/v1/validator';

@Injectable()
export class MockInterceptor implements HttpInterceptor {
Expand All @@ -29,6 +30,16 @@ export class MockInterceptor implements HttpInterceptor {
body: mock[request.method as keyof RestObject],
}));
}
if (this.contains(request.url, KEYMANAGER_API_VALIDATOR_PREFIX )) {
if(this.contains(request.url,'feerecipient')){
let mock = KeymanagerAPIMocks['/eth/v1/validator/{pubkey}/feerecipient'];
return of(new HttpResponse({
status: 200,
body: mock[request.method as keyof RestObject],
}));
}

}
if (this.contains(request.url, VALIDATOR_API_PREFIX)) {
endpoint = this.extractEndpoint(request.url, VALIDATOR_API_PREFIX);
}
Expand Down
14 changes: 12 additions & 2 deletions src/app/modules/core/mocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ValidatorParticipation } from 'src/app/proto/eth/v1alpha1/validator';
import {
Account, BackupAccountsResponse, BeaconStatusResponse, GenerateMnemonicResponse, ImportKeystoresResponse, InitializeAuthResponse, ListAccountsResponse, WalletResponse
} from 'src/app/proto/validator/accounts/v2/web_api';
import { DeleteAccountsResponse } from 'src/app/proto/validator/accounts/v2/web_api_keymanager-api';
import { DeleteAccountsResponse, ListFeeRecipientResponse } from 'src/app/proto/validator/accounts/v2/web_api_keymanager-api';
import { GWEI_PER_ETHER } from '../constants';


Expand Down Expand Up @@ -583,7 +583,17 @@ export const KeymanagerAPIMocks = {
}],
slashing_protection: "{\"metadata\":{\"interchange_format_version\":\"5\",\"genesis_validators_root\":\"0x043db0d9a83813551ee2f33450d23797757d430911a9320530ad8a0eabc43efb\"},\"data\":[{\"pubkey\":\"0x8d65ffe7b65ee8e7c3e14a474a360f16722920ef8c0ef1da6f942fd6ddc3628c1edda7f57cf28d7ddc7fc9cb9745df60\",\"signed_blocks\":[],\"signed_attestations\":[{\"source_epoch\":\"71793\",\"target_epoch\":\"71794\",\"signing_root\":\"0xc996259c3456818eb1cc5102a88316ff505d940a9840a5205f54ba3334a60aa8\"},{\"source_epoch\":\"71794\",\"target_epoch\":\"71795\",\"signing_root\":\"0x0ea5c7312ebd4a0a009fd92780972a0ad7391eb12143218359b1019140da4e53\"},{\"source_epoch\":\"71795\",\"target_epoch\":\"71796\",\"signing_root\":\"0xe09c4e38834637c4588fde948827709959e9d177d93207f2d00951bb4ddc18ff\"},{\"source_epoch\":\"71796\",\"target_epoch\":\"71797\",\"signing_root\":\"0xf13f47d87685ffc6258cbd831dd1e375cf54cfa1702ef3ec92a8d230ca353c44\"},{\"source_epoch\":\"71797\",\"target_epoch\":\"71798\",\"signing_root\":\"0x57ab41e44ca77e9bb26a9a1a2950eda83ba1f900091a200bcab6bab4bc921c0c\"},{\"source_epoch\":\"71798\",\"target_epoch\":\"71799\",\"signing_root\":\"0x444eed11867e86d3ce6b97e08d7d8bb87f403583a9940f364eaba04c862e78f5\"},{\"source_epoch\":\"71799\",\"target_epoch\":\"71800\",\"signing_root\":\"0xa0fcc0fbf0b7f24d18fc3f4efbd474fc762fc4ed2ca3a0798d4b07aeee1b144b\"},{\"source_epoch\":\"71800\",\"target_epoch\":\"71801\",\"signing_root\":\"0xcdd9a1454f93632fb3f4da8f0654306c045af6b8490a8558780cc27b43d763a2\"},{\"source_epoch\":\"71801\",\"target_epoch\":\"71802\",\"signing_root\":\"0x4e473e9bcafd60f6c5c53eceb8cdcdfa0b2a165830fd82243e8b682e373b248e\"},{\"source_epoch\":\"71802\",\"target_epoch\":\"71803\",\"signing_root\":\"0xf98c0a28d46739bbdee389281b087635fbc7c58ddb27e9736d9376500b865674\"},{\"source_epoch\":\"71803\",\"target_epoch\":\"71804\",\"signing_root\":\"0x52ffb97763758fbe1a22783f98983b78f580815fb41fada3bb0cfc886e0838d1\"},{\"source_epoch\":\"71804\",\"target_epoch\":\"71805\",\"signing_root\":\"0x2388327613c16412baf6b3429603dbfc31fa84490877e57706d464b26a720241\"},{\"source_epoch\":\"71805\",\"target_epoch\":\"71806\",\"signing_root\":\"0xfc5b7a3bee9e71c76691ab392ed9e21730eba735f129eaf150c754eb9b0ebd56\"},{\"source_epoch\":\"71806\",\"target_epoch\":\"71807\",\"signing_root\":\"0xa4071f5852bbde14c2128027682dfa8e9c166d3affc42fd45b7b1120d16cb126\"},{\"source_epoch\":\"71807\",\"target_epoch\":\"71808\",\"signing_root\":\"0xb8ee3840e82dd2d8982d551b079dc77d64d74e93045207315ab67531c345db88\"},{\"source_epoch\":\"71808\",\"target_epoch\":\"71809\",\"signing_root\":\"0x700567d637657c615410e60e45ccc1f313173242480454cdc3ac1c239c54876e\"},{\"source_epoch\":\"71809\",\"target_epoch\":\"71810\",\"signing_root\":\"0xa6ad2005a5675a9b33cf08ac1f0fafb3b96afd0acb004e2daccee981e0bc6ca0\"},{\"source_epoch\":\"71810\",\"target_epoch\":\"71811\",\"signing_root\":\"0xf78c31f4158dce92c386261a48d77b47813deaaeefc8679790eb69decc6e2dcb\"},{\"source_epoch\":\"71811\",\"target_epoch\":\"71812\",\"signing_root\":\"0xfd21111aa0c2e2ddd7b599378b23095dd176d9fb6f86805e103ad9ea2b602a8a\"},{\"source_epoch\":\"71812\",\"target_epoch\":\"71813\",\"signing_root\":\"0xa50d236f1063b04b34a2b9d0e8f3fb56e495ebf26e992e8d8b89af66b7d28243\"},{\"source_epoch\":\"71813\",\"target_epoch\":\"71814\",\"signing_root\":\"0x0b9df665c3b717d5ffc7b14a6cad4b883edb9b3068c5ded219522d626f8b38ac\"},{\"source_epoch\":\"71814\",\"target_epoch\":\"71815\",\"signing_root\":\"0xfe9f887500d0797f5340d336495020795e896c95eed15a6d990c63bcffffca48\"},{\"source_epoch\":\"71815\",\"target_epoch\":\"71816\",\"signing_root\":\"0xfe5b638cade977c527bcb0cab500ad2bd1d992432c22641f08b376210f76322d\"},{\"source_epoch\":\"71816\",\"target_epoch\":\"71817\",\"signing_root\":\"0x0efb9c40d8771746a7bfeb8e50da9ee281c91b6e315f538b677251989592ccf4\"},{\"source_epoch\":\"71817\",\"target_epoch\":\"71818\",\"signing_root\":\"0x534238e82f5a637076166143acacccd45b629b5f271020d9917f2a307b5b3daf\"},{\"source_epoch\":\"71818\",\"target_epoch\":\"71819\",\"signing_root\":\"0x7bcb82fb0cb70e14e6d14981d8c372b096af2051048bb765644fee0b34e06af3\"},{\"source_epoch\":\"71819\",\"target_epoch\":\"71820\",\"signing_root\":\"0x79341fd23fac19f66b62729c675f0841269dd51b1796d982f726bb3697b945a3\"},{\"source_epoch\":\"71820\",\"target_epoch\":\"71821\",\"signing_root\":\"0x4cee1928b36d80d846ac4ad03798604415ce9df67f8aae2154a5143c467f7045\"},{\"source_epoch\":\"71821\",\"target_epoch\":\"71822\",\"signing_root\":\"0xd52fd16a994e5c0321acbe99f75050ab35f34a40f830bdf2c7e22639fde32bba\"},{\"source_epoch\":\"71822\",\"target_epoch\":\"71823\",\"signing_root\":\"0x72f7fabc617608017e405fb4b7d38a5cb32415d02f680aba4197399a4297e85c\"},{\"source_epoch\":\"71823\",\"target_epoch\":\"71824\",\"signing_root\":\"0x833d572c3175a3da0ff52daa77a1c43930f5cfb1bd76d949e709b7499f2ce976\"},{\"source_epoch\":\"71824\",\"target_epoch\":\"71825\",\"signing_root\":\"0xb41571cdf4b6bddac9de6fd9d8dd307db80f4bdaffd59f9a5453c9e369e63857\"},{\"source_epoch\":\"71825\",\"target_epoch\":\"71826\",\"signing_root\":\"0x6128c2914d23051a0dd850271ef82d5cee0ea060da153d9557b8d79ca4df0f96\"},{\"source_epoch\":\"71826\",\"target_epoch\":\"71827\",\"signing_root\":\"0xf360a01608e54d16da72133511b7d6a5e535bf2a6ec2f8e793424126808d50e5\"},{\"source_epoch\":\"71827\",\"target_epoch\":\"71828\",\"signing_root\":\"0xb54d8eaa2f26c61f3b63d4691f88970c6ee0d4180e704f7e1333a7de7381ebc7\"},{\"source_epoch\":\"71828\",\"target_epoch\":\"71829\",\"signing_root\":\"0x0b6dfce0ba24e05930e91ace94988785d3334d45f33356801895a07ba7a1c820\"},{\"source_epoch\":\"71829\",\"target_epoch\":\"71830\",\"signing_root\":\"0xb36a3059dac0dd3c76d7557b67c2134f7b01f40e636e37149a3656dd0b77bb63\"},{\"source_epoch\":\"71830\",\"target_epoch\":\"71831\",\"signing_root\":\"0xa82420dd16591544680bd55eb05491a69fe2ed37fab16d6f4b858c2f45dfbc90\"},{\"source_epoch\":\"71831\",\"target_epoch\":\"71832\",\"signing_root\":\"0x2a59b5be18b4223ccf1ccb895c9bd959808d96e252cb098485ef73816b818a4c\"},{\"source_epoch\":\"71832\",\"target_epoch\":\"71833\",\"signing_root\":\"0xbb031ce7ed980a545eccdf330a109c748003e816a9376a6ca51bf126037f1520\"},{\"source_epoch\":\"71833\",\"target_epoch\":\"71834\",\"signing_root\":\"0x9efcb9af1e9ed8b9b0c05726159d1bf9c8190a5b6b4630e4a0ba48ddb328e444\"},{\"source_epoch\":\"71834\",\"target_epoch\":\"71835\",\"signing_root\":\"0x1b48057c770f415b4c2a67197dcb7eebcf05a90f87ee818034291fa3e0f2cdbc\"},{\"source_epoch\":\"71835\",\"target_epoch\":\"71836\",\"signing_root\":\"0x33f7a8c54ef1e3e353537901a195a0be1ffbc0d9922f15fc18e836f7d9d49d13\"},{\"source_epoch\":\"71836\",\"target_epoch\":\"71837\",\"signing_root\":\"0x1289e1b831366e1dce42eacf93ce357ce4793c143251953d43d086f8ce738b93\"},{\"source_epoch\":\"71837\",\"target_epoch\":\"71838\",\"signing_root\":\"0x09abf84d9b8b528ce6fdfb4d6b456a380f6def97ac33600680c740a58c4824af\"},{\"source_epoch\":\"71838\",\"target_epoch\":\"71839\",\"signing_root\":\"0x8b5201fa5038f1aedd85258352a9380a70d423cd23300fd4cf27ae20957f65e0\"},{\"source_epoch\":\"71839\",\"target_epoch\":\"71840\",\"signing_root\":\"0x13ccfddfc270176a5379218974d7e62984b07cf23025cb4b579a4c6a209549cf\"},{\"source_epoch\":\"71840\",\"target_epoch\":\"71841\",\"signing_root\":\"0x9f2249c6bdfeec47b52609189c4befbb5b39debf5cafa25d7d280a65b08c6ccf\"},{\"source_epoch\":\"71841\",\"target_epoch\":\"71842\",\"signing_root\":\"0xe4a6f8bdd4d6cc255ad80c39618e8f3c2c64ace4d5bde8aedc90bcecad6713b8\"},{\"source_epoch\":\"71842\",\"target_epoch\":\"71843\",\"signing_root\":\"0xc495fe48309ebbccb7e888772a0174978a57e37f135f418d822081de62422bc9\"},{\"source_epoch\":\"72225\",\"target_epoch\":\"72226\",\"signing_root\":\"0x399d34a7be6120925668009f2fb6bc1cdcde7ffa9d96ef5bdf6f13db49bdef93\"},{\"source_epoch\":\"72226\",\"target_epoch\":\"72227\",\"signing_root\":\"0x0b81c94db5d4cf6a12c9198a407f811019464899126ae16b040bd25fa3f52a47\"}]}]}"
} as DeleteAccountsResponse,
} as RestObject
} as RestObject,
'/eth/v1/validator/{pubkey}/feerecipient':{
'GET':{
data:{
pubkey:"0xaadaf653799229200378369ee7d6d9fdbdcdc2788143ed44f1ad5f2367c735e83a37c5bb80d7fb917de73a61bbcf00c4",
ethaddress: "0xasdfsadfsfsfsdfsadfsdafsadfsadsdafasdf"
}
} as ListFeeRecipientResponse,
'POST':{},
'DELETE':{},
}as RestObject
}

export interface RestObject {
Expand Down
19 changes: 18 additions & 1 deletion src/app/modules/core/services/validator.service.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, zip } from 'rxjs';
import { Observable, Subject, zip } from 'rxjs';
import { map, share, switchMap } from 'rxjs/operators';
import {
ValidatorBalances, Validators, ValidatorSummaryResponse
} from 'src/app/proto/eth/v1alpha1/beacon_chain';
import { VersionResponse } from 'src/app/proto/validator/accounts/v2/web_api';
import { ListFeeRecipientResponse, SetFeeRecipientRequest } from 'src/app/proto/validator/accounts/v2/web_api_keymanager-api';
import { base64ToHex } from '../utils/hex-util';
import { EnvironmenterService } from './environmenter.service';
import { WalletService } from './wallet.service';

Expand All @@ -24,6 +26,9 @@ export class ValidatorService {
private environmenter: EnvironmenterService,
) { }
private apiUrl = this.environmenter.env.validatorEndpoint;
private keymanagerUrl = this.environmenter.env.keymanagerEndpoint;

refreshTableDataTrigger$ = new Subject<Boolean>();

version$: Observable<VersionResponse> = this.http.get<VersionResponse>(`${this.apiUrl}/health/version`).pipe(
share(),
Expand Down Expand Up @@ -57,6 +62,18 @@ export class ValidatorService {
return this.http.get<Validators>(`${this.apiUrl}/beacon/validators${params}`);
}

getFeeRecipient(publicKey:string): Observable< ListFeeRecipientResponse>{
return this.http.get<ListFeeRecipientResponse>(`${this.keymanagerUrl}/validator/${base64ToHex(publicKey)}/feerecipient`)
}

setFeeRecipient(publicKey:string,request: SetFeeRecipientRequest){
return this.http.post(`${this.keymanagerUrl}/validator/${publicKey}/feerecipient`,request)
}

deleteFeeRecipient(publicKey:string){
return this.http.delete(`${this.keymanagerUrl}/validator/${publicKey}/feerecipient`)
}

balances(
publicKeys: string[],
pageIndex: number,
Expand Down
2 changes: 1 addition & 1 deletion src/app/modules/core/services/wallet.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class WalletService {
) {}

private apiUrl = this.environmenter.env.validatorEndpoint;
private keymanagerApiUrl = this.environmenter.env.keymanagerEndpoint;
private keymanagerApiUrl = this.environmenter.env.keymanagerEndpoint+"/keystores";

// Observables.
walletConfig$: Observable<WalletResponse> = this.http
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@
{{element.publicKey | base64tohex}}
</td>
</ng-container>

<ng-container matColumnDef="correctlyVotedSource">
<ng-container matColumnDef="feeRecipient">
<th mat-header-cell *matHeaderCellDef>Fee Recipient</th>
<td mat-cell *matCellDef="let element" class="truncate">
{{element.feeRecipient }}
</td>
</ng-container>
<ng-container matColumnDef="correctlyVotedSource" >
<th mat-header-cell *matHeaderCellDef>Correctly voted source</th>
<td mat-cell *matCellDef="let element">
<div [className]="element.correctlyVotedSource ? 'check green' :
Expand All @@ -35,7 +40,7 @@
</td>
</ng-container>

<ng-container matColumnDef="correctlyVotedTarget">
<ng-container matColumnDef="correctlyVotedTarget" >
<th mat-header-cell *matHeaderCellDef>Voted target</th>
<td mat-cell *matCellDef="let element">
<div [className]="element.correctlyVotedTarget ? 'check green' :
Expand All @@ -44,11 +49,10 @@
</td>
</ng-container>

<ng-container matColumnDef="correctlyVotedHead">
<ng-container matColumnDef="correctlyVotedHead" class="max-w-sm">
<th mat-header-cell *matHeaderCellDef>Voted head</th>
<td mat-cell *matCellDef="let element">
<div

[className]="element.correctlyVotedHead ?
'check green' :
'cross red'">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import { MatTableDataSource } from '@angular/material/table';

import { BigNumber } from 'ethers';
import { ValidatorSummaryResponse } from 'src/app/proto/eth/v1alpha1/beacon_chain';
import { throwError } from 'rxjs';
import { catchError, map, take, tap, takeUntil, filter } from 'rxjs/operators';
import { EMPTY, forkJoin, Observable, throwError, zip } from 'rxjs';
import { catchError, map, take, tap, takeUntil, filter, switchMap, flatMap, concatMap, mergeMap } from 'rxjs/operators';
import { ValidatorService } from '../../../core/services/validator.service';
import { BaseComponent } from '../../../shared/components/base.component';
import { UserService } from '../../../shared/services/user.service';
import { ListFeeRecipientResponse } from 'src/app/proto/validator/accounts/v2/web_api_keymanager-api';
import { base64ToHex } from 'src/app/modules/core/utils/hex-util';

export interface ValidatorListItem {
publicKey: string;
feeRecipient: string;
currentEffectiveBalances: string;
correctlyVotedSource: boolean;
correctlyVotedTarget: boolean;
Expand All @@ -31,6 +34,7 @@ export class ValidatorPerformanceListComponent
implements OnInit {
displayedColumns: string[] = [
'publicKey',
'feeRecipient',
'correctlyVotedSource',
'correctlyVotedTarget',
'correctlyVotedHead',
Expand All @@ -56,6 +60,7 @@ export class ValidatorPerformanceListComponent
.pipe(
map((performance: ValidatorSummaryResponse) => {
const list: ValidatorListItem[] = [];

if (performance) {
for (let i = 0; i < performance.public_keys.length; i++) {
// converting snake_case to camelCase
Expand All @@ -78,12 +83,29 @@ export class ValidatorPerformanceListComponent
}
return list;
}),
tap((result) => {
this.dataSource = new MatTableDataSource(result);
switchMap((list:ValidatorListItem[]) => {
const arrayOfRequests: Observable<ListFeeRecipientResponse>[] = [];
list.forEach((item:ValidatorListItem)=>{
arrayOfRequests.push(this.validatorService.getFeeRecipient(item.publicKey));
});
return forkJoin(arrayOfRequests).pipe(
map((res:ListFeeRecipientResponse[]) => {
res.forEach((r)=>{
let item = list.find((obj)=>base64ToHex(obj.publicKey) === r.data.pubkey)
if(item){
item.feeRecipient = r.data.ethaddress
}
})
return list;
})
)
}),
tap((list:ValidatorListItem[])=>{
this.dataSource = new MatTableDataSource(list);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
this.loading = false;
this.noData = result.length === 0;
this.noData = list.length === 0;
}),
catchError((err) => {
this.loading = false;
Expand Down Expand Up @@ -119,3 +141,7 @@ export class ValidatorPerformanceListComponent
this.userService.changeGainsAndLosesPageSize(ev.pageSize);
}
}
function compactMap(arg0: (res: ListFeeRecipientResponse[]) => void): import("rxjs").OperatorFunction<ListFeeRecipientResponse[], unknown> {
throw new Error('Function not implemented.');
}

Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,14 @@
<th mat-header-cell *matHeaderCellDef mat-sort-header> Validator Index</th>
<td mat-cell *matCellDef="let row"> {{row.index}} </td>
</ng-container>

<ng-container matColumnDef="feeRecipient">
<th mat-header-cell *matHeaderCellDef mat-sort-header> Fee Recipient</th>
<td mat-cell *matCellDef="let row"
matTooltipPosition="left"
matTooltip="Copy to Clipboard"
(click)="copyFeeRecipientToClipboard(row.feeRecipient)"
class="cursor-pointer"> {{row.feeRecipient | slice:0:8 }}... </td>
</ng-container>
<ng-container matColumnDef="balance">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ETH Balance</th>
<td mat-cell *matCellDef="let row">
Expand Down Expand Up @@ -86,7 +93,7 @@
<div class="flex">
<app-icon-trigger-select
[menuItems]="menuItems"
[data]="row.publicKey"
[data]="row"
icon="more_horiz"></app-icon-trigger-select>
<a mat-icon-button
matTooltip="Exit validator"
Expand Down
Loading