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

Namadillo: Phase 2 - Claim Rewards + useTransaction #1100

Merged
merged 22 commits into from
Sep 14, 2024
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a6aaf12
feat(namadillo): creating useBalances hook
pedrorezende Sep 10, 2024
cb2e11b
feat(namadillo): separating colors and other props from tailwind config
pedrorezende Sep 10, 2024
b8a90a9
feat(components): adding label property to PieChart
pedrorezende Sep 10, 2024
5f8c1d1
feat: refactoring balance props to be reused between staking and over…
pedrorezende Sep 10, 2024
d306168
feat(namadillo): fixing overview chart
pedrorezende Sep 10, 2024
2db10ba
feat(namadillo): adding mocks for useBalance
pedrorezende Sep 10, 2024
b4d267d
feat(namadillo): adding tests for NamBalanceContainer
pedrorezende Sep 10, 2024
0bb9144
feat(namadillo): adding footer to AccountOverview
pedrorezende Sep 10, 2024
2020ae8
feat(namadillo): replacing by Panel component
pedrorezende Sep 10, 2024
94869b7
feat(namadillo): claim rewards component
pedrorezende Sep 10, 2024
5267c50
feat(namadillo): enabling staking rewards
pedrorezende Sep 11, 2024
8edab46
temp: claiming rewards wip
pedrorezende Sep 12, 2024
8482495
feat(namadillo): adding useTransaction hook and refactoring claim rew…
pedrorezende Sep 12, 2024
e70a8f9
refactor(namadillo): applying useTransaction to IncrementBonding
pedrorezende Sep 12, 2024
eedf50f
feat(namadillo): adding useTransaction on Unstake flow
pedrorezende Sep 12, 2024
e32d231
feat(namadillo): applying useTransaction to redelegate
pedrorezende Sep 12, 2024
c93fb76
chore: fixing some merge conflicts
pedrorezende Sep 12, 2024
b05de63
feat(namadillo): applying useTransaction to Withdraw
pedrorezende Sep 12, 2024
986028c
feat(namadillo): writing tests for StakingRewardsPanel
pedrorezende Sep 12, 2024
9edfc7d
feat(namadillo): adding claim and stake
pedrorezende Sep 13, 2024
38922ec
feat(namadillo): writing tests for StakingRewards
pedrorezende Sep 13, 2024
eddb079
fix(namadillo): fixing staking rewards not updating
pedrorezende Sep 13, 2024
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
6 changes: 6 additions & 0 deletions apps/extension/src/Approvals/Commitment.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { TxType } from "@heliax/namada-sdk/web";
import {
BondProps,
ClaimRewardsProps,
CommitmentDetailProps,
RedelegateProps,
RevealPkProps,
Expand Down Expand Up @@ -103,7 +104,12 @@ const renderContent = (tx: CommitmentDetailProps): ReactNode => {
<>Reveal public key for address {formatAddress(revealTx.publicKey)}</>
);

case TxType.ClaimRewards:
const claimTx = tx as ClaimRewardsProps;
return <>Claiming rewards from {formatAddress(claimTx.validator)}</>;

// TODO: continue implementing other types in the next phases

default:
return <></>;
}
Expand Down
10 changes: 7 additions & 3 deletions apps/namadillo/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,12 @@ module.exports = {
modulePathIgnorePatterns: ["e2e-tests"],
moduleDirectories: ["src", "node_modules"],
verbose: true,
moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
prefix: "<rootDir>/src/",
}),
moduleNameMapper: {
...pathsToModuleNameMapper(compilerOptions.paths, {
prefix: "<rootDir>/src/",
}),
"^.+\\.svg$": "jest-transformer-svg",
"\\.css": "identity-obj-proxy",
},
setupFilesAfterEnv: ["<rootDir>/src/setupTests.ts"],
};
3 changes: 3 additions & 0 deletions apps/namadillo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
"test:watch": "yarn wasm:build:test && yarn jest --watchAll=true",
"test:coverage": "yarn wasm:build:test && yarn test --coverage",
"test:ci": "jest",
"test:watch:only": "yarn test --watchAll=true",
"e2e-test": "PLAYWRIGHT_BASE_URL=http://localhost:3000 yarn playwright test",
"e2e-test:headed": "PLAYWRIGHT_BASE_URL=http://localhost:3000 yarn playwright test --project=chromium --headed",
"wasm:build": "node ./scripts/build.js --release",
Expand Down Expand Up @@ -106,10 +107,12 @@
"eslint-plugin-react-hooks": "^4.6.0",
"globals": "^15.9.0",
"history": "^5.3.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-create-mock-instance": "^2.0.0",
"jest-environment-jsdom": "^29.7.0",
"jest-fetch-mock": "^3.0.3",
"jest-transformer-svg": "^2.0.2",
"local-cors-proxy": "^1.1.0",
"postcss": "^8.4.32",
"release-it": "^17.0.1",
Expand Down
59 changes: 43 additions & 16 deletions apps/namadillo/src/App/AccountOverview/AccountOverview.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,61 @@
import { Stack } from "@namada/components";
import { Panel, Stack } from "@namada/components";
import { Intro } from "App/Common/Intro";
import { PageWithSidebar } from "App/Common/PageWithSidebar";
import MainnetRoadmap from "App/Sidebars/MainnetRoadmap";
import { namadaExtensionConnectedAtom } from "atoms/settings";
import { StakingRewardsPanel } from "App/Staking/StakingRewardsPanel";
import {
applicationFeaturesAtom,
namadaExtensionConnectedAtom,
} from "atoms/settings";
import clsx from "clsx";
import { useAtomValue } from "jotai";
import { AccountBalanceContainer } from "./AccountBalanceContainer";
import { NamBalanceContainer } from "./NamBalanceContainer";
import { NavigationFooter } from "./NavigationFooter";

export const AccountOverview = (): JSX.Element => {
const isConnected = useAtomValue(namadaExtensionConnectedAtom);
const { claimRewardsEnabled, maspEnabled } = useAtomValue(
applicationFeaturesAtom
);

const fullView = claimRewardsEnabled || maspEnabled;
const fullWidthClassName = clsx({ "col-span-2": !isConnected });

return (
<PageWithSidebar>
<div
className={clsx(
"flex items-center bg-black rounded-sm w-full",
fullWidthClassName
)}
>
<div className={clsx("flex w-full", fullWidthClassName)}>
{!isConnected && (
<div className="w-[420px] mx-auto">
<Intro />
</div>
<section className="flex rounded-sm items-center w-full bg-black">
<div className="w-[420px] mx-auto">
<Intro />
</div>
</section>
)}
{isConnected && (
<Stack gap={5} className="my-auto min-w-[365px] mx-auto py-12">
<AccountBalanceContainer />
<NavigationFooter />
</Stack>

{isConnected && !fullView && (
<section className="flex items-center bg-black rounded-sm w-full">
<Stack gap={5} className="my-auto min-w-[365px] mx-auto py-12">
<AccountBalanceContainer />
<NavigationFooter />
</Stack>
</section>
)}

{isConnected && fullView && (
<section className="flex flex-col w-full rounded-sm min-h-full gap-2">
<div className="grid grid-cols-[1.25fr_1fr] gap-2">
<Panel className="pl-4 pr-6 py-5">
<NamBalanceContainer />
</Panel>
<Panel>
<StakingRewardsPanel />
</Panel>
</div>
<Panel className="flex items-center flex-1 justify-center">
<NavigationFooter />
</Panel>
</section>
)}
</div>
{isConnected && (
Expand Down
91 changes: 91 additions & 0 deletions apps/namadillo/src/App/AccountOverview/NamBalanceContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { Stack } from "@namada/components";
import { AtomErrorBoundary } from "App/Common/AtomErrorBoundary";
import { BalanceChart } from "App/Common/BalanceChart";
import { NamCurrency } from "App/Common/NamCurrency";
import BigNumber from "bignumber.js";
import { useBalances } from "hooks/useBalances";
import { colors } from "theme";

type NamBalanceListItemProps = {
title: string;
color: string;
amount: BigNumber;
};

const NamBalanceListItem = ({
title,
color,
amount,
}: NamBalanceListItemProps): JSX.Element => {
return (
<li
className="leading-5 bg-neutral-900 px-4 py-3 rounded-sm min-w-[165px]"
aria-description={`${title} amount is ${amount.toString()} NAM`}
>
<span className="flex items-center text-xs gap-1.5">
<i className="w-2 h-2 rounded-full" style={{ background: color }} />
{title}
</span>
<NamCurrency
amount={amount}
className="text-lg pl-3.5"
currencySignClassName="hidden"
/>
</li>
);
};

export const NamBalanceContainer = (): JSX.Element => {
const {
balanceQuery,
stakeQuery,
isLoading,
isSuccess,
availableAmount,
bondedAmount,
shieldedAmount,
unbondedAmount,
withdrawableAmount,
totalAmount,
} = useBalances();

return (
<div className="flex gap-4 text-white">
<AtomErrorBoundary
result={[balanceQuery, stakeQuery]}
niceError="Unable to load balances"
>
<div className="flex items-center w-full">
<BalanceChart
view="total"
isLoading={isLoading}
isSuccess={isSuccess}
availableAmount={availableAmount}
bondedAmount={bondedAmount}
shieldedAmount={shieldedAmount}
unbondedAmount={unbondedAmount}
withdrawableAmount={withdrawableAmount}
totalAmount={totalAmount}
/>
<Stack gap={2} as="ul">
<NamBalanceListItem
title="Available NAM"
color={colors.balance}
amount={availableAmount}
/>
<NamBalanceListItem
title="Staked NAM"
color={colors.bond}
amount={bondedAmount}
/>
<NamBalanceListItem
title="Unbonded NAM"
color={colors.unbond}
amount={unbondedAmount.plus(withdrawableAmount)}
/>
</Stack>
</div>
</AtomErrorBoundary>
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { cleanup, render, screen } from "@testing-library/react";
import BigNumber from "bignumber.js";
import { mockUseBalances } from "hooks/__mocks__/mockUseBalance";
import { AtomWithQueryResult } from "jotai-tanstack-query";
import { NamBalanceContainer } from "../NamBalanceContainer";

jest.mock("hooks/useBalances", () => ({
useBalances: jest.fn(),
}));

describe("Component: NamBalanceContainer", () => {
beforeEach(() => {
jest.clearAllMocks();
});

test("renders error boundary when queries fail", () => {
// Check if the error message from AtomErrorBoundary is displayed
const execute = (
balanceQueryError: boolean,
stakeQueryError: boolean
): void => {
mockUseBalances({
balanceQuery: { isError: balanceQueryError } as AtomWithQueryResult,
stakeQuery: { isError: stakeQueryError } as AtomWithQueryResult,
isLoading: false,
isSuccess: false,
});
render(<NamBalanceContainer />);
expect(screen.getByText(/Unable to load balances/i)).toBeInTheDocument();
cleanup();
jest.clearAllMocks();
};

execute(true, true);
execute(false, true);
execute(true, false);
});

test("renders balance items when data is loaded", () => {
mockUseBalances({
availableAmount: new BigNumber(100),
bondedAmount: new BigNumber(50),
unbondedAmount: new BigNumber(30),
withdrawableAmount: new BigNumber(25),
totalAmount: new BigNumber(200),
});

render(<NamBalanceContainer />);

// Check if the list items for each balance type are rendered
expect(screen.getByText(/Available NAM/i)).toBeInTheDocument();
expect(screen.getByText(/Staked NAM/i)).toBeInTheDocument();
expect(screen.getByText(/Unbonded NAM/i)).toBeInTheDocument();

// Check if the amounts are displayed correctly

// Available:
expect(screen.getByText("100 NAM")).toBeInTheDocument();

// Bonded / Staked
expect(screen.getByText("50 NAM")).toBeInTheDocument();

// Unbonded + Withdraw
expect(screen.queryByText("30 NAM")).toBeNull();
expect(screen.queryByText("25 NAM")).toBeNull();
expect(screen.getByText("55 NAM")).toBeInTheDocument();
});
});
5 changes: 5 additions & 0 deletions apps/namadillo/src/App/AppRoutes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import GovernanceRoutes from "./Governance/routes";
import SettingsRoutes from "./Settings/routes";
import { SignMessages } from "./SignMessages/SignMessages";
import MessageRoutes from "./SignMessages/routes";
import { StakingRewards } from "./Staking/StakingRewards";
import StakingRoutes from "./Staking/routes";
import SwitchAccountRoutes from "./SwitchAccount/routes";

Expand Down Expand Up @@ -60,6 +61,10 @@ export const MainRoutes = (): JSX.Element => {
element={<SignMessages />}
errorElement={<RouteErrorBoundary />}
/>
<Route
path={`${StakingRoutes.claimRewards().url}`}
element={<StakingRewards />}
/>
</Routes>
<ScrollRestoration />
</>
Expand Down
Loading
Loading