Skip to content

Commit

Permalink
feat: add modal button on logged in
Browse files Browse the repository at this point in the history
  • Loading branch information
icfor committed Feb 28, 2024
1 parent 77f81cb commit 2ebea4b
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 33 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Xion Staking

A proof of concept application to stake tokens in Xion, using the native
authentication via the dashboard.
2 changes: 1 addition & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import StakingPage from "@/features/staking/components/page";

export default function Page(): JSX.Element {
export default function Page() {
return <StakingPage />;
}
74 changes: 51 additions & 23 deletions src/features/staking/components/logged-in.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
"use client";

import { useAbstraxionSigningClient } from "@burnt-labs/abstraxion";
import { useAbstraxionSigningClient, useModal } from "@burnt-labs/abstraxion";
import { Button } from "@burnt-labs/ui";
import type { Validator } from "cosmjs-types/cosmos/staking/v1beta1/staking";
import Link from "next/link";
import { memo, useState } from "react";
import { memo, useMemo, useState } from "react";

import type { StakingState } from "../context";
import {
claimRewardsAction,
stakeValidator,
unstakeValidator,
setRedelegateAction,
stakeValidatorAction,
unstakeValidatorAction,
} from "../context/actions";
import { useStaking } from "../context/hooks";
import type { StakeAddresses } from "../lib/core/base";
Expand Down Expand Up @@ -58,16 +59,20 @@ function StakingPage() {
const [isLoading, setIsLoading] = useState(false);
const { delegations, tokens, unbondings, validators } = staking.state;
const { client } = useAbstraxionSigningClient();

const validatorsMap: Record<string, undefined | Validator> =
validators?.items.reduce<Record<string, undefined | Validator>>(
(acc, validator) => {
acc[validator.operatorAddress] = validator;

return acc;
},
{},
) || {};
const [, setShowAbstraxion] = useModal();

const validatorsMap: Record<string, undefined | Validator> = useMemo(
() =>
validators?.items.reduce<Record<string, undefined | Validator>>(
(acc, validator) => {
acc[validator.operatorAddress] = validator;

return acc;
},
{},
) || {},
[validators],
);

return (
<>
Expand All @@ -76,6 +81,15 @@ function StakingPage() {
<div>
<b>{account.bech32Address}</b>
</div>
<div>
<Button
onClick={() => {
setShowAbstraxion(true);
}}
>
Open Settings
</Button>
</div>
{tokens && (
<div>
Tokens: <b>{formatCoin(tokens)}</b>
Expand Down Expand Up @@ -112,11 +126,13 @@ function StakingPage() {
validator: validator.operatorAddress,
};

unstakeValidator(addresses, client, staking).finally(
() => {
setIsLoading(false);
},
);
unstakeValidatorAction(
addresses,
client,
staking,
).finally(() => {
setIsLoading(false);
});
}}
>
Undelegate
Expand Down Expand Up @@ -147,7 +163,17 @@ function StakingPage() {
<Button
disabled={isLoading}
onClick={() => {
// @TODO
if (!client) return;

setIsLoading(true);

setRedelegateAction(
account.bech32Address,
client,
staking,
).finally(() => {
setIsLoading(false);
});
}}
>
Redelelegate
Expand Down Expand Up @@ -208,9 +234,11 @@ function StakingPage() {
validator: validator.operatorAddress,
};

stakeValidator(addresses, client, staking).finally(() => {
setIsLoading(false);
});
stakeValidatorAction(addresses, client, staking).finally(
() => {
setIsLoading(false);
},
);
}}
validator={validator}
/>
Expand Down
26 changes: 20 additions & 6 deletions src/features/staking/context/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
getRewards,
getUnbondingDelegations,
getValidatorsList,
setRedelegate,
stakeAmount,
unstakeAmount,
} from "../lib/core/base";
Expand All @@ -18,7 +19,7 @@ import {
setValidators,
} from "./reducer";

export const fetchStakingData = async (
export const fetchStakingDataAction = async (
address: string,
staking: StakingContextType,
) => {
Expand Down Expand Up @@ -105,7 +106,7 @@ export const fetchStakingData = async (
}
};

export const stakeValidator = async (
export const stakeValidatorAction = async (
addresses: StakeAddresses,
client: SigningClient,
staking: StakingContextType,
Expand All @@ -115,10 +116,10 @@ export const stakeValidator = async (
denom: "uxion",
});

await fetchStakingData(addresses.delegator, staking);
await fetchStakingDataAction(addresses.delegator, staking);
};

export const unstakeValidator = async (
export const unstakeValidatorAction = async (
addresses: StakeAddresses,
client: SigningClient,
staking: StakingContextType,
Expand All @@ -131,7 +132,7 @@ export const unstakeValidator = async (
// eslint-disable-next-line no-console
console.log("debug: actions.ts: result", result);

await fetchStakingData(addresses.delegator, staking);
await fetchStakingDataAction(addresses.delegator, staking);
};

export const claimRewardsAction = async (
Expand All @@ -144,5 +145,18 @@ export const claimRewardsAction = async (
// eslint-disable-next-line no-console
console.log("debug: actions.ts: result", result);

await fetchStakingData(addresses.delegator, staking);
await fetchStakingDataAction(addresses.delegator, staking);
};

export const setRedelegateAction = async (
delegatorAddress: string,
client: SigningClient,
staking: StakingContextType,
) => {
const result = await setRedelegate(delegatorAddress, client);

// eslint-disable-next-line no-console
console.log("debug: actions.ts: result", result);

await fetchStakingDataAction(delegatorAddress, staking);
};
4 changes: 2 additions & 2 deletions src/features/staking/context/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useContext, useEffect, useRef } from "react";

import type { StakingContextType } from ".";
import { StakingContext } from ".";
import { fetchStakingData } from "./actions";
import { fetchStakingDataAction } from "./actions";

export const useStaking = () => {
const stakingRef = useRef<StakingContextType>({} as StakingContextType);
Expand Down Expand Up @@ -31,7 +31,7 @@ export const useStakingSync = () => {

useEffect(() => {
if (isLoggedIn && address) {
fetchStakingData(address, staking);
fetchStakingDataAction(address, staking);
}
}, [isLoggedIn, address, staking]);
};
25 changes: 25 additions & 0 deletions src/features/staking/lib/core/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { useAbstraxionSigningClient } from "@burnt-labs/abstraxion";
import type { EncodeObject } from "@cosmjs/proto-signing";
import type {
Coin,
MsgBeginRedelegateEncodeObject,
MsgDelegateEncodeObject,
MsgUndelegateEncodeObject,
MsgWithdrawDelegatorRewardEncodeObject,
Expand All @@ -18,6 +19,7 @@ import { Tendermint34Client } from "@cosmjs/tendermint-rpc";
import BigNumber from "bignumber.js";
import { MsgWithdrawDelegatorReward } from "cosmjs-types/cosmos/distribution/v1beta1/tx";
import {
MsgBeginRedelegate,
MsgDelegate,
MsgUndelegate,
} from "cosmjs-types/cosmos/staking/v1beta1/tx";
Expand Down Expand Up @@ -229,3 +231,26 @@ export const claimRewards = async (

return await client.signAndBroadcast(addresses.delegator, [msgAny], fee);
};

// @TODO: Pass the target delegator
export const setRedelegate = async (
delegatorAddress: string,
client: NonNullable<SigningClient>,
) => {
const msg = MsgBeginRedelegate.fromPartial({
delegatorAddress,
});

const msgAny: MsgBeginRedelegateEncodeObject = {
typeUrl: "/cosmos.staking.v1beta1.MsgBeginRedelegate",
value: msg,
};

const fee: StdFee = await getCosmosFee({
address: delegatorAddress,
client,
msgs: [msgAny],
});

return await client.signAndBroadcast(delegatorAddress, [msgAny], fee);
};
3 changes: 2 additions & 1 deletion src/features/staking/lib/core/coins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ export const formatCoin = (coin: Coin) => {
return `${amount.toFormat()} ${resolved.denom}`;
};

export const getEmptyXionCoin = () => ({ amount: "0", denom: "xion" });
export const getEmptyXionCoin = () =>
({ amount: "0", denom: "xion" }) satisfies Coin;

export const sumAllCoins = (coins: Coin[]) =>
coins.reduce(
Expand Down

0 comments on commit 2ebea4b

Please sign in to comment.