Skip to content

Commit

Permalink
support phase 1 fp name
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremy-babylonlabs committed Jan 13, 2025
1 parent f110d27 commit eae3417
Show file tree
Hide file tree
Showing 16 changed files with 452 additions and 205 deletions.
9 changes: 3 additions & 6 deletions src/app/api/getFinalityProviders.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { isValidUrl } from "@/utils/url";

import { Pagination } from "../types/api";
import {
FinalityProvider,
FinalityProviderState,
} from "../types/finalityProviders";
import { FinalityProvider } from "../types/finalityProviders";

import { apiWrapper } from "./apiWrapper";

Expand All @@ -20,7 +17,7 @@ interface FinalityProvidersAPIResponse {

interface FinalityProviderAPI {
description: DescriptionAPI;
state: FinalityProviderState;
state: "active" | "standby";
commission: string;
btc_pk: string;
active_tvl: number;
Expand Down Expand Up @@ -60,7 +57,7 @@ export const getFinalityProviders = async ({

const response = await apiWrapper(
"GET",
"/v2/finality-providers",
"/v1/finality-providers",
"Error getting finality providers",
{ query: params },
);
Expand Down
99 changes: 99 additions & 0 deletions src/app/api/getFinalityProvidersV2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { isValidUrl } from "@/utils/url";

import { Pagination } from "../types/api";
import {
FinalityProviderState,
FinalityProviderV2,
} from "../types/finalityProvidersV2";

import { apiWrapper } from "./apiWrapper";

export interface PaginatedFinalityProviders {
finalityProviders: FinalityProviderV2[];
pagination: Pagination;
}

interface FinalityProvidersAPIResponse {
data: FinalityProviderAPI[];
pagination: Pagination;
}

interface FinalityProviderAPI {
description: DescriptionAPI;
state: FinalityProviderState;
commission: string;
btc_pk: string;
active_tvl: number;
total_tvl: number;
active_delegations: number;
total_delegations: number;
}

interface DescriptionAPI {
moniker: string;
identity: string;
website: string;
security_contact: string;
details: string;
}

export const getFinalityProvidersV2 = async ({
key,
pk,
sortBy,
order,
name,
}: {
key: string;
name?: string;
sortBy?: string;
order?: "asc" | "desc";
pk?: string;
}): Promise<PaginatedFinalityProviders> => {
const params = {
pagination_key: key,
finality_provider_pk: pk,
sort_by: sortBy,
order,
name,
};

const response = await apiWrapper(
"GET",
"/v2/finality-providers",
"Error getting finality providers",
{ query: params },
);

const finalityProvidersAPIResponse: FinalityProvidersAPIResponse =
response.data;
const finalityProvidersAPI: FinalityProviderAPI[] =
finalityProvidersAPIResponse.data;

const finalityProviders = finalityProvidersAPI.map(
(fp: FinalityProviderAPI): FinalityProviderV2 => ({
description: {
moniker: fp.description.moniker,
identity: fp.description.identity,
website: isValidUrl(fp.description.website)
? fp.description.website
: "",
securityContact: fp.description.security_contact,
details: fp.description.details,
},
state: fp.state,
commission: fp.commission,
btcPk: fp.btc_pk,
activeTVLSat: fp.active_tvl,
totalTVLSat: fp.total_tvl,
activeDelegations: fp.active_delegations,
totalDelegations: fp.total_delegations,
}),
);

const pagination: Pagination = {
next_key: finalityProvidersAPIResponse.pagination.next_key,
};

return { finalityProviders, pagination };
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

import { Hash } from "@/app/components/Hash/Hash";
import {
FinalityProvider,
FinalityProviderState,
FinalityProviderStateLabels,
} from "@/app/types/finalityProviders";
FinalityProviderV2,
} from "@/app/types/finalityProvidersV2";
import { getNetworkConfigBTC } from "@/config/network/btc";
import { satoshiToBtc } from "@/utils/btc";
import { maxDecimals } from "@/utils/maxDecimals";
Expand All @@ -20,7 +20,7 @@ export const finalityProviderColumns = [
{
key: "moniker",
header: "Finality Provider",
render: (_: unknown, row?: FinalityProvider) => {
render: (_: unknown, row?: FinalityProviderV2) => {
if (!row) return null;
return (
<div className="flex items-center gap-2">
Expand All @@ -37,7 +37,7 @@ export const finalityProviderColumns = [
</div>
);
},
sorter: (a?: FinalityProvider, b?: FinalityProvider) => {
sorter: (a?: FinalityProviderV2, b?: FinalityProviderV2) => {
const monikerA = a?.description?.moniker || "";
const monikerB = b?.description?.moniker || "";
return monikerA.localeCompare(monikerB);
Expand All @@ -50,7 +50,7 @@ export const finalityProviderColumns = [
if (value == null) return "Unknown";
return mapStatus(value as FinalityProviderState);
},
sorter: (a?: FinalityProvider, b?: FinalityProvider) => {
sorter: (a?: FinalityProviderV2, b?: FinalityProviderV2) => {
const stateA = a?.state || "unknown";
const stateB = b?.state || "unknown";
return stateA.localeCompare(stateB);
Expand All @@ -59,7 +59,7 @@ export const finalityProviderColumns = [
{
key: "btcPk",
header: `${coinSymbol} PK`,
render: (_: unknown, row?: FinalityProvider) => {
render: (_: unknown, row?: FinalityProviderV2) => {
if (!row?.btcPk) return null;
return <Hash value={row.btcPk} address small noFade />;
},
Expand All @@ -72,7 +72,7 @@ export const finalityProviderColumns = [
if (isNaN(amount)) return "-";
return `${maxDecimals(satoshiToBtc(amount), 8)} ${coinSymbol}`;
},
sorter: (a?: FinalityProvider, b?: FinalityProvider) => {
sorter: (a?: FinalityProviderV2, b?: FinalityProviderV2) => {
const valueA = a?.activeTVLSat ?? 0;
const valueB = b?.activeTVLSat ?? 0;
return valueA - valueB;
Expand All @@ -86,7 +86,7 @@ export const finalityProviderColumns = [
if (isNaN(commission)) return "-";
return `${maxDecimals(commission * 100, 2)}%`;
},
sorter: (a?: FinalityProvider, b?: FinalityProvider) => {
sorter: (a?: FinalityProviderV2, b?: FinalityProviderV2) => {
const commissionA = Number(a?.commission) || 0;
const commissionB = Number(b?.commission) || 0;
return commissionA - commissionB;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Select } from "@babylonlabs-io/bbn-core-ui";

import { useFinalityProviderState } from "@/app/state/FinalityProviderState";
import { useFinalityProviderV2State } from "@/app/state/FinalityProviderV2State";

const options = [
{ value: "active", label: "Active" },
{ value: "inactive", label: "Inactive" },
];

export const FinalityProviderFilter = () => {
const { filterValue, handleFilter } = useFinalityProviderState();
const { filterValue, handleFilter } = useFinalityProviderV2State();

return (
<Select
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { Input } from "@babylonlabs-io/bbn-core-ui";
import { useCallback } from "react";
import { RiSearchLine } from "react-icons/ri";

import { useFinalityProviderState } from "@/app/state/FinalityProviderState";
import { useFinalityProviderV2State } from "@/app/state/FinalityProviderV2State";

export const FinalityProviderSearch = () => {
const { handleSearch, searchValue } = useFinalityProviderState();
const { handleSearch, searchValue } = useFinalityProviderV2State();

const onSearchChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useMemo } from "react";

import warningOctagon from "@/app/assets/warning-octagon.svg";
import warningTriangle from "@/app/assets/warning-triangle.svg";
import { useFinalityProviderState } from "@/app/state/FinalityProviderState";
import { useFinalityProviderV2State } from "@/app/state/FinalityProviderV2State";

import { finalityProviderColumns } from "./FinalityProviderColumns";
import { StatusView } from "./FinalityProviderTableStatusView";
Expand All @@ -25,7 +25,7 @@ export const FinalityProviderTable = ({
filterValue,
hasError,
isRowSelectable,
} = useFinalityProviderState();
} = useFinalityProviderV2State();

const tableData = useMemo(() => {
if (!finalityProviders) return [];
Expand Down
31 changes: 22 additions & 9 deletions src/app/components/Staking/FinalityProviders/FinalityProviders.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
import { Suspense } from "react";

import {
Heading,
HiddenField,
Text,
useFormContext,
} from "@babylonlabs-io/bbn-core-ui";
import { LoadingTableList } from "@/app/components/Loading/Loading";

import { FinalityProviderFilter } from "./FinalityProviderFilter";
import { FinalityProviderSearch } from "./FinalityProviderSearch";
import { FinalityProviderTable } from "./FinalityProviderTable";

export const FinalityProviders = () => {
const FinalityProviderContent = () => {
const { setValue } = useFormContext();

return (
<div className="flex flex-col gap-4">
<Heading variant="h5" className="text-primary-dark">
Step 1
</Heading>
<Text variant="body1" className="text-primary-dark">
Select a Finality Provider
</Text>

<>
<div className="flex flex-col md:flex-row gap-4">
<div className="flex-1">
<FinalityProviderSearch />
Expand All @@ -41,6 +37,23 @@ export const FinalityProviders = () => {
/>

<HiddenField name="finalityProvider" defaultValue="" />
</>
);
};

export const FinalityProviders = () => {
return (
<div className="flex flex-col gap-4">
<Heading variant="h5" className="text-primary-dark">
Step 1
</Heading>
<Text variant="body1" className="text-primary-dark">
Select a Finality Provider
</Text>

<Suspense fallback={<LoadingTableList />}>
<FinalityProviderContent />
</Suspense>
</div>
);
};
2 changes: 1 addition & 1 deletion src/app/hooks/client/api/useFinalityProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { ONE_MINUTE } from "@/app/constants";
import { useError } from "@/app/context/Error/ErrorContext";
import { ErrorState } from "@/app/types/errors";

const FINALITY_PROVIDERS_KEY = "GET_FINALITY_PROVIDERS_V2_KEY";
const FINALITY_PROVIDERS_KEY = "GET_FINALITY_PROVIDERS_V1_KEY";

interface Params {
pk?: string;
Expand Down
67 changes: 67 additions & 0 deletions src/app/hooks/client/api/useFinalityProvidersV2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { useInfiniteQuery } from "@tanstack/react-query";
import { useEffect } from "react";

import {
type PaginatedFinalityProviders,
getFinalityProvidersV2,
} from "@/app/api/getFinalityProvidersV2";
import { ONE_MINUTE } from "@/app/constants";
import { useError } from "@/app/context/Error/ErrorContext";
import { ErrorState } from "@/app/types/errors";

const FINALITY_PROVIDERS_KEY = "GET_FINALITY_PROVIDERS_V2_KEY";

interface Params {
pk?: string;
name?: string;
sortBy?: string;
order?: "asc" | "desc";
}

export function useFinalityProvidersV2({
pk,
sortBy,
order,
name,
}: Params = {}) {
const { isErrorOpen, handleError, captureError } = useError();

const query = useInfiniteQuery({
queryKey: [FINALITY_PROVIDERS_KEY],
queryFn: ({ pageParam = "" }) =>
getFinalityProvidersV2({ key: pageParam, pk, sortBy, order, name }),
getNextPageParam: (lastPage) =>
lastPage?.pagination?.next_key !== ""
? lastPage?.pagination?.next_key
: null,
initialPageParam: "",
refetchInterval: ONE_MINUTE,
placeholderData: (prev) => prev,
select: (data) => {
const flattenedData = data.pages.reduce<PaginatedFinalityProviders>(
(acc, page) => {
acc.finalityProviders.push(...page.finalityProviders);
acc.pagination = page.pagination;
return acc;
},
{ finalityProviders: [], pagination: { next_key: "" } },
);
return flattenedData;
},
retry: (failureCount) => {
return !isErrorOpen && failureCount <= 3;
},
});

useEffect(() => {
handleError({
error: query.error,
hasError: query.isError,
errorState: ErrorState.SERVER_ERROR,
refetchFunction: query.refetch,
});
captureError(query.error);
}, [query.isError, query.error, query.refetch, handleError, captureError]);

return query;
}
Loading

0 comments on commit eae3417

Please sign in to comment.