Skip to content

Commit

Permalink
Merge pull request #4 from forbole/feat/redelegate
Browse files Browse the repository at this point in the history
feat: redelegation
  • Loading branch information
0x7u authored May 14, 2024
2 parents 208e4ab + 8b157a7 commit e07a9c0
Show file tree
Hide file tree
Showing 13 changed files with 986 additions and 430 deletions.
11 changes: 10 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ const nextConfig = {
typescript: {
ignoreBuildErrors: process.env.QUICK_BUILD === "true",
},
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 's3.amazonaws.com',
port: '',
pathname: '**',
},
],
},
...(useProxy
? {
rewrites: async () => [
Expand All @@ -22,7 +32,6 @@ const nextConfig = {
process.env.NEXT_PUBLIC_IS_DEPLOYMENT === "true"
? "/xion-staking"
: undefined,
output: "export",
}),
};

Expand Down
578 changes: 252 additions & 326 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"type-check": "tsc --noEmit"
},
"dependencies": {
"@burnt-labs/abstraxion": "^1.0.0-alpha.39",
"@burnt-labs/abstraxion": "^1.0.0-alpha.43",
"@burnt-labs/constants": "^0.1.0-alpha.6",
"@burnt-labs/ui": "^0.1.0-alpha.7",
"@cosmjs/cosmwasm-stargate": "^0.32.2",
Expand Down
3 changes: 3 additions & 0 deletions public/down-arrow.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
18 changes: 14 additions & 4 deletions src/features/core/components/table.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Image from "next/image";
import type { PropsWithChildren } from "react";

import { chevron } from "../lib/icons";
Expand Down Expand Up @@ -65,14 +66,23 @@ export const HeaderTitleBase = <SortMethod extends string>({
);
};

export const ValidatorLogo = ({ logo }: { logo: null | string }) => (
export const ValidatorLogo = ({
height = 50,
logo,
width = 50,
}: {
height?: number;
logo: null | string;
width?: number;
}) => (
<div className="flex items-center justify-start">
{logo ? (
<img
<Image
alt="Validator logo"
className="block w-[50px] rounded-full"
className="block rounded-full"
height={height}
src={logo}
style={{ height: 50, minHeight: 50, minWidth: 50, width: 50 }}
width={width}
/>
) : (
<span className="block h-[50px] w-[50px] rounded-full bg-defaultLogo" />
Expand Down
137 changes: 91 additions & 46 deletions src/features/staking/components/delegation-details.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Coin } from "@cosmjs/stargate";
import BigNumber from "bignumber.js";
import {
BondStatus,
Expand Down Expand Up @@ -130,6 +131,20 @@ const DelegationRowBase = ({
isMobile ? "flex md:hidden" : "hidden md:flex",
].join(" ")}
>
<ButtonLink
onClick={() => {
if (!validator) return;

staking.dispatch(
setModalOpened({
content: { validator },
type: "redelegate",
}),
);
}}
>
Redelegate
</ButtonLink>
<ButtonLink
disabled={!getCanClaimRewards(delegation?.rewards) || disabledProp}
onClick={() => {
Expand Down Expand Up @@ -254,44 +269,41 @@ const DelegationRowBase = ({

const DelegationRow = memo(DelegationRowBase);

type UnbondingRowProps = {
disabled?: boolean;
type UnbondingRedelegationRowProps = {
balance: Coin;
completionTime: number;
onCancel?: () => void;
stakingRef: ReturnType<typeof useStaking>;
unbonding: NonNullable<StakingState["unbondings"]>["items"][number];
status: string;
validator?: Validator;
validatorAddress: string;
};

const UnbondingRow = ({
disabled,
const UnbondingRedelegationRow = ({
balance,
completionTime,
onCancel,
stakingRef,
unbonding,
status,
validator,
}: UnbondingRowProps) => {
validatorAddress,
}: UnbondingRedelegationRowProps) => {
const { staking } = stakingRef;

const logo = useValidatorLogo(
validator?.description.identity,
validator?.operatorAddress,
);

const validatorAddress = unbonding.validator;

useEffect(() => {
if (validatorAddress) {
getAndSetValidatorAction(validatorAddress, staking);
}
}, [validatorAddress, staking]);

const cancelProps = {
disabled,
onClick: () => {
staking.dispatch(
setModalOpened({
content: { unbondings: [unbonding] },
type: "cancel-unstaking",
}),
);
},
disabled: !onCancel,
onClick: onCancel,
};

return (
Expand All @@ -310,16 +322,18 @@ const UnbondingRow = ({
</div>
</div>
<div className="text-right">
<TokenColors text={formatCoin(unbonding.balance)} />
<TokenColors text={formatCoin(balance)} />
</div>
<div className="text-right">Unbonding</div>
<div className="text-right">
{formatUnbondingCompletionTime(unbonding.completionTime)}
{formatUnbondingCompletionTime(completionTime)}
</div>
<div className="text-right">
<ButtonPill {...cancelProps} variant="danger">
Cancel Unstake
</ButtonPill>
{!!onCancel && (
<ButtonPill {...cancelProps} variant="danger">
Cancel Unstake
</ButtonPill>
)}
</div>
</div>
<div
Expand All @@ -338,21 +352,23 @@ const UnbondingRow = ({
</div>
<div className="flex w-full flex-row justify-between">
<span>Amount</span>
<TokenColors text={formatCoin(unbonding.balance)} />
<TokenColors text={formatCoin(balance)} />
</div>
<div className="flex w-full flex-row justify-between">
<span>Status</span>
<span>Unbonding</span>
<span>{status}</span>
</div>
<div className="flex w-full flex-row justify-between">
<span>Completion</span>
{formatUnbondingCompletionTime(unbonding.completionTime)}
</div>
<div className="flex w-full flex-row justify-end">
<ButtonPill {...cancelProps} variant="danger">
Cancel Unstake
</ButtonPill>
{formatUnbondingCompletionTime(completionTime)}
</div>
{!!onCancel && (
<div className="flex w-full flex-row justify-end">
<ButtonPill {...cancelProps} variant="danger">
Cancel Unstake
</ButtonPill>
</div>
)}
</div>
</>
);
Expand Down Expand Up @@ -393,12 +409,13 @@ const DelegationDetails = () => {

const validatorsMap = getAllValidators(staking.state);

const { delegations, unbondings } = staking.state;
const { delegations, redelegations, unbondings } = staking.state;

const hasDelegations = !!delegations?.items.length;
const hasUnbondings = !!unbondings?.items.length;
const hasRedelegations = !!redelegations?.items.length;

if (!hasDelegations && !hasUnbondings) {
if (!hasDelegations && !hasUnbondings && !hasRedelegations) {
return null;
}

Expand Down Expand Up @@ -487,9 +504,12 @@ const DelegationDetails = () => {
</div>
);
})()}
{hasUnbondings &&
{(hasUnbondings || hasRedelegations) &&
(() => {
const sortedUnbondings = unbondings.items.slice().sort((a, b) => {
const sortedUnbondings = [
...(unbondings?.items ?? []),
...(redelegations?.items ?? []),
].sort((a, b) => {
switch (unbondingsSortMethod) {
case "amount-asc":
case "amount-desc":
Expand Down Expand Up @@ -517,12 +537,14 @@ const DelegationDetails = () => {
return (
<div className={wrapperStyle}>
<div className={headerStyle} style={gridStyle}>
<UnbondingHeaderTitle mobile>Unstakings</UnbondingHeaderTitle>
<UnbondingHeaderTitle mobile>
Unstakings/Redelegations
</UnbondingHeaderTitle>
<UnbondingHeaderTitle
onSort={setUnbondingsSortMethod}
rigthAlign
sort={unbondingsSortMethod}
sorting={["staked-asc", "staked-desc"]}
sorting={["amount-asc", "amount-desc"]}
>
<div className="text-right">Staked Amount</div>
</UnbondingHeaderTitle>
Expand All @@ -533,19 +555,42 @@ const DelegationDetails = () => {
onSort={setUnbondingsSortMethod}
rigthAlign
sort={unbondingsSortMethod}
sorting={["date-asc", "date-desc"]}
sorting={["completion-asc", "completion-desc"]}
>
<div className="text-right">Completion Time</div>
</UnbondingHeaderTitle>
</div>
{sortedUnbondings.map((unbonding, index) => (
<UnbondingRow
key={index}
stakingRef={stakingRef}
unbonding={unbonding}
validator={validatorsMap[unbonding.validator]}
/>
))}
{sortedUnbondings.map((unbondingRedelegation, index) => {
const isUnbonding = "validator" in unbondingRedelegation;

const validatorAddress = isUnbonding
? unbondingRedelegation.validator
: unbondingRedelegation.dstValidator;

const onCancel = isUnbonding
? () => {
staking.dispatch(
setModalOpened({
content: { unbondings: [unbondingRedelegation] },
type: "cancel-unstaking",
}),
);
}
: undefined;

return (
<UnbondingRedelegationRow
balance={unbondingRedelegation.balance}
completionTime={unbondingRedelegation.completionTime}
key={index}
onCancel={onCancel}
stakingRef={stakingRef}
status={isUnbonding ? "Unbonding" : "Redelegation"}
validator={validatorsMap[validatorAddress]}
validatorAddress={validatorAddress}
/>
);
})}
</div>
);
})()}
Expand Down
Loading

0 comments on commit e07a9c0

Please sign in to comment.