Skip to content

Commit

Permalink
changes the validators voucher display to show compliance status and …
Browse files Browse the repository at this point in the history
…the valid/total ratio
  • Loading branch information
soaresa authored and minaxolone committed Jul 24, 2024
1 parent df492f0 commit bd7f81e
Show file tree
Hide file tree
Showing 9 changed files with 133 additions and 72 deletions.
1 change: 1 addition & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"node": "^20.11.1"
},
"scripts": {
"clean": "rimraf dist",
"build": "nest build",
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
"start": "nest start",
Expand Down
73 changes: 51 additions & 22 deletions api/src/ol/models/validator.model.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,54 @@
import { Field, ObjectType } from '@nestjs/graphql';
import BN from 'bn.js';

export interface IVoucherInput {
address: string;
epoch: number;
}

@ObjectType('Voucher')
export class Voucher {
public constructor(input: IVoucherInput) {
this.address = input.address;
this.epoch = input.epoch;
}

@Field(() => String)
public address: string;

@Field(() => Number)
public epoch: number;
}

interface IVouchesInput {
valid: number;
total: number;
compliant: boolean;
vouchers: Voucher[];
}

@ObjectType('Vouches')
export class Vouches {
public constructor(input: IVouchesInput) {
this.valid = input.valid;
this.total = input.total;
this.compliant = input.compliant;
this.vouchers = input.vouchers;
}

@Field(() => Number)
public valid: number;

@Field(() => Number)
public total: number;

@Field(() => Boolean)
public compliant: boolean;

@Field(() => [Voucher])
public vouchers: Voucher[];
}

@ObjectType('ValidatorCurrentBid')
export class GqlValidatorCurrentBid {
public constructor(input: GqlValidatorCurrentBidInput) {
Expand Down Expand Up @@ -52,7 +100,7 @@ interface ValidatorInput {
unlocked?: number;
votingPower: BN;
grade?: GqlValidatorGrade | null;
vouches: GqlVouch[];
vouches: Vouches;
currentBid: GqlValidatorCurrentBid;
city?: string | null;
country?: string | null;
Expand Down Expand Up @@ -97,8 +145,8 @@ export class Validator {
@Field(() => GqlValidatorGrade, { nullable: true })
public grade?: GqlValidatorGrade | null;

@Field(() => [GqlVouch], { nullable: true })
public vouches?: GqlVouch[];
@Field(() => Vouches, { nullable: true })
public vouches?: Vouches;

@Field(() => GqlValidatorCurrentBid, { nullable: true })
public currentBid?: GqlValidatorCurrentBid;
Expand All @@ -112,22 +160,3 @@ export class Validator {
@Field(() => [String], { nullable: true })
public auditQualification?: [string] | null;
}

interface GqlVouchInput {
epoch: number;
address: string;
}

@ObjectType('Vouch')
export class GqlVouch {
public constructor(input: GqlVouchInput) {
this.epoch = input.epoch;
this.address = input.address;
}

@Field(() => Number)
public epoch: number;

@Field(() => String)
public address: string;
}
46 changes: 23 additions & 23 deletions api/src/ol/validators/validators.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import BN from 'bn.js';

import { OlService } from '../ol.service.js';
import { PrismaService } from '../../prisma/prisma.service.js';
import { Validator, GqlVouch } from '../models/validator.model.js';
import { Validator, Vouches, Voucher } from '../models/validator.model.js';
import { parseAddress } from '../../utils.js';

@Injectable()
Expand Down Expand Up @@ -76,7 +76,8 @@ export class ValidatorsService {
const slowWallet = await this.olService.getSlowWallet(validator.address);
const unlocked = Number(slowWallet?.unlocked);

const vouches = await this.getVouches(validator.address);
let vouches = await this.getVouches(validator.address);

const currentBid = await this.olService.getCurrentBid(validator.address);
return new Validator({
inSet: validator.inSet,
Expand Down Expand Up @@ -104,41 +105,40 @@ export class ValidatorsService {
return auditQualification[0] as [string];
}

public async getVouches(address: Buffer): Promise<GqlVouch[]> {
const allVouchesRes = await this.olService.aptosClient.getAccountResource(
public async getVouches(address: Buffer): Promise<Vouches> {
const allVouchersRes = await this.olService.aptosClient.getAccountResource(
`0x${address.toString('hex')}`,
'0x1::vouch::MyVouches',
);

const validVouchesRes = await this.olService.aptosClient.view({
function: '0x1::vouch::true_friends',
type_arguments: [],
arguments: [`0x${address.toString('hex')}`],
});

const allVouches = allVouchesRes.data as {
const allVouchers = allVouchersRes.data as {
epoch_vouched: string[];
my_buddies: string[];
};

const all = allVouches.my_buddies.map((address, index) => {
const all = allVouchers.my_buddies.map((address, index) => {
return {
address: parseAddress(address).toString('hex').toLocaleUpperCase(),
epoch: Number(allVouches.epoch_vouched[index]),
epoch: Number(allVouchers.epoch_vouched[index]),
};
});

let validVouches = validVouchesRes[0] as string[];
validVouches = validVouches.map((address) =>
parseAddress(address).toString('hex').toLocaleUpperCase(),
);
const activeVouches = all.filter((vouch) => validVouches.includes(vouch.address));
const validVouchersRes = await this.olService.aptosClient.view({
function: '0x1::proof_of_fee::get_valid_vouchers_in_set',
type_arguments: [],
arguments: [`0x${address.toString('hex')}`],
});

return activeVouches.map((vouch) => {
return new GqlVouch({
address: parseAddress(vouch.address).toString('hex').toLocaleUpperCase(),
epoch: Number(vouch.epoch),
});
return new Vouches({
compliant: validVouchersRes[0] as boolean,
valid: Number(validVouchersRes[1]),
total: all.length,
vouchers: all.map((vouch) => {
return new Voucher({
address: parseAddress(vouch.address).toString('hex').toLocaleUpperCase(),
epoch: Number(vouch.epoch),
});
}),
});
}
}
19 changes: 13 additions & 6 deletions api/src/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,18 @@ type UserTransactionCollection {
items: [GqlUserTransactionDeprecated!]!
}

type Voucher {
address: String!
epoch: Float!
}

type Vouches {
valid: Float!
total: Float!
compliant: Boolean!
vouchers: [Voucher!]!
}

type ValidatorCurrentBid {
currentBid: Float!
expirationEpoch: Float!
Expand All @@ -60,18 +72,13 @@ type Validator {
country: String
votingPower: BigInt!
grade: ValidatorGrade
vouches: [Vouch!]
vouches: Vouches
currentBid: ValidatorCurrentBid
balance: Float
unlocked: Float
auditQualification: [String!]
}

type Vouch {
epoch: Float!
address: String!
}

type Account {
address: Bytes!
balance: Decimal
Expand Down
2 changes: 1 addition & 1 deletion web-app/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ const configMap = new Map<string, Config>([
},
],
[
'localhost',
'127.0.0.1',
{
apiHost: API_HOST,
dataApiHost: VITE_DATA_API_HOST,
Expand Down
14 changes: 7 additions & 7 deletions web-app/src/modules/core/routes/Validators/Validators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@ const GET_VALIDATORS = gql`
failedBlocks
proposedBlocks
}
grade {
compliant
failedBlocks
proposedBlocks
}
vouches {
address
epoch
compliant
valid
total
vouchers {
address
epoch
}
}
currentBid {
currentBid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,8 @@ const ValidatorsTable: FC<ValidatorsTableProps> = ({ validators }) => {
value2 = b.auditQualification ? b.auditQualification[b.auditQualification.length - 1] : '';
break;
case 'vouches':
value1 = a.vouches.length;
value2 = b.vouches.length;
value1 = a.vouches.valid;
value2 = b.vouches.valid;
break;
case 'currentBid':
value1 = a.currentBid ? a.currentBid.currentBid : 0;
Expand Down
31 changes: 24 additions & 7 deletions web-app/src/modules/core/routes/Validators/components/Vouches.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,43 @@
import { FC, useState } from 'react';
import { Dialog, DialogPanel, DialogTitle, Transition, TransitionChild } from '@headlessui/react';
import { XMarkIcon } from '@heroicons/react/24/outline';
import { CheckIcon, XMarkIcon } from '@heroicons/react/24/outline';

import AccountAddress from '../../../../ui/AccountAddress';

interface Vouch {
address: string;
epoch: number;
interface Vouches {
compliant: boolean;
valid: number;
total: number;
vouchers: {
address: string;
epoch: number;
}[];
}

interface VouchesProps {
vouches: Vouch[];
vouches: Vouches;
}

const Vouches: FC<VouchesProps> = ({ vouches }) => {
const [open, setOpen] = useState(!true);

const sortedVouchers = vouches.vouchers.slice().sort((a, b) => {
if (a.epoch === b.epoch) {
return a.address.localeCompare(b.address);
}
return b.epoch - a.epoch;
});

return (
<>
<div>
<button type="button" onClick={() => setOpen(true)}>
{vouches.length.toLocaleString()}
{vouches.compliant ? (
<CheckIcon className="w-5 h-5 text-green-500 inline" style={{ marginTop: '-3px' }} />
) : (
<XMarkIcon className="w-5 h-5 text-red-500 inline" style={{ marginTop: '-3px' }} />
)}
{vouches.valid} / {vouches.total}
</button>
</div>

Expand Down Expand Up @@ -77,7 +94,7 @@ const Vouches: FC<VouchesProps> = ({ vouches }) => {
</tr>
</thead>
<tbody className="divide-y divide-gray-200 bg-white">
{vouches.map((vouch, index) => (
{sortedVouchers.map((vouch, index) => (
<tr key={index} className="text-sm text-[#141414] text-center">
<td className="px-2 py-2">{index + 1}</td>
<td className="px-2 py-2">{vouch.epoch}</td>
Expand Down
15 changes: 11 additions & 4 deletions web-app/src/modules/interface/Validator.interface.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
interface Vouches {
valid: number;
total: number;
compliant: boolean;
vouchers: {
address: string;
epoch: number;
}[];
}

export interface IValidator {
address: string;
inSet: boolean;
index: number;
votingPower: number;
balance?: number;
unlocked?: number;
vouches: {
epoch: number;
address: string;
}[];
vouches: Vouches;
grade: {
compliant: boolean;
failedBlocks: number;
Expand Down

0 comments on commit bd7f81e

Please sign in to comment.