diff --git a/src/api.graphql b/src/api.graphql
index 9fe0406b5..fbf7dffb2 100644
--- a/src/api.graphql
+++ b/src/api.graphql
@@ -56,6 +56,7 @@ query TransactionResult($txId: TxId!) {
blockHash
blockIndex
txStatus
+ outputState
}
}
}
diff --git a/src/renderer/components/core/Layout/UserInfo/MigrateButton.tsx b/src/renderer/components/core/Layout/UserInfo/MigrateButton.tsx
new file mode 100644
index 000000000..a2e295cd9
--- /dev/null
+++ b/src/renderer/components/core/Layout/UserInfo/MigrateButton.tsx
@@ -0,0 +1,42 @@
+import { motion } from "framer-motion";
+import React, { MouseEvent, useCallback } from "react";
+import { T } from "src/renderer/i18n";
+import { styled } from "src/renderer/stitches.config";
+
+export const Button = styled(motion.button, {
+ appearance: "none",
+ backgroundColor: "#dc9c2d",
+ border: "none",
+ padding: "5px 1rem",
+ "&:disabled": {
+ backgroundColor: "$gray",
+ color: "white",
+ },
+});
+
+const transifexTags = "v2/MigrateButton";
+
+interface MigrateButtonProps {
+ onClick: () => void;
+ loading: boolean;
+}
+
+export function MigrateButton({ loading, onClick }: MigrateButtonProps) {
+ const eventListener = useCallback<(e: MouseEvent) => void>(
+ (e) => {
+ e.stopPropagation();
+ onClick();
+ },
+ [onClick],
+ );
+
+ return (
+
+ );
+}
diff --git a/src/renderer/components/core/Layout/UserInfo/index.tsx b/src/renderer/components/core/Layout/UserInfo/index.tsx
index b1bb699bc..a3e1e7d79 100644
--- a/src/renderer/components/core/Layout/UserInfo/index.tsx
+++ b/src/renderer/components/core/Layout/UserInfo/index.tsx
@@ -13,16 +13,17 @@ import {
useClaimStakeRewardLazyQuery,
useTransactionResultLazyQuery,
useCheckPatchTableSubscription,
+ useStakeLazyQuery,
} from "src/generated/graphql";
import AccountBoxIcon from "@material-ui/icons/AccountBox";
-import LaunchIcon from "@material-ui/icons/Launch";
import FileCopyIcon from "@material-ui/icons/FileCopy";
import goldIconUrl from "src/renderer/resources/ui-main-icon-gold.png";
import monsterIconUrl from "src/renderer/resources/monster.png";
import { getRemain } from "src/utils/monsterCollection/utils";
import ClaimCollectionRewardsOverlay from "src/renderer/views/ClaimCollectionRewardsOverlay";
+import MigrateCollectionRewardsOverlay from "src/renderer/views/MigrateCollectionRewardsOverlay";
import { Button, ClaimButton } from "./ClaimButton";
import { clipboard } from "electron";
import { toast } from "react-hot-toast";
@@ -37,6 +38,7 @@ import deepEqual from "deep-equal";
import { StakeStatusButton } from "./StakeStatus";
import { useStore } from "src/utils/useStore";
import Decimal from "decimal.js";
+import { MigrateButton } from "./MigrateButton";
const UserInfoStyled = styled(motion.ul, {
position: "fixed",
@@ -93,29 +95,47 @@ export default function UserInfo() {
const isCollecting = !!startedBlockIndex && startedBlockIndex > 0;
const [claimLoading, setClaimLoading] = useState(false);
const [isMigratable, setIsMigratable] = useState(
- isCollecting &&
+ !!deposit &&
+ new Decimal(deposit).gt(0) &&
+ tip !== 0 &&
+ isCollecting &&
!deepEqual(stakeRewards, latestSheet?.stateQuery.latestStakeRewards, {
strict: true,
}),
);
+
useEffect(() => {
const txStatus = result?.transaction.transactionResult.txStatus;
if (!txStatus || txStatus === TxStatus.Staging) return;
stopPolling?.();
setClaimLoading(false);
- if (txStatus === TxStatus.Success) {
- toast.success(
- t("Successfully sent rewards to {name} #{address}", {
- _tags: "v2/monster-collection",
- name: claimedAvatar.current!.name,
- address: claimedAvatar.current!.address.slice(2),
- }),
- );
- refetch();
+ if (canClaim) {
+ if (txStatus === TxStatus.Success) {
+ toast.success(
+ t("Successfully sent rewards to {name} #{address}", {
+ _tags: "v2/monster-collection",
+ name: claimedAvatar.current!.name,
+ address: claimedAvatar.current!.address.slice(2),
+ }),
+ );
+ refetch();
+ } else {
+ toast.error(t("Failed to claim your reward."));
+ console.error("Claim transaction failed: ", result);
+ }
} else {
- toast.error(t("Failed to claim your reward."));
- console.error("Claim transaction failed: ", result);
+ if (txStatus === TxStatus.Success) {
+ toast.success(
+ t("Successfully migrated your staking.", {
+ _tags: "v2/monster-collection",
+ }),
+ );
+ refetch();
+ } else {
+ toast.error(t("Failed to migrate your staking."));
+ console.error("Migration transaction failed: ", result);
+ }
}
}, [result]);
@@ -148,9 +168,22 @@ export default function UserInfo() {
});
},
});
+
+ const [requestMigrationTx] = useStakeLazyQuery({
+ fetchPolicy: "network-only",
+ onCompleted: ({ actionTxQuery: { stake } }) => {
+ tx(stake).then((txId) => {
+ if (txId!.data)
+ fetchResult({
+ variables: { txId: txId!.data.stageTransaction },
+ });
+ });
+ },
+ });
const tx = useTx();
const [openDialog, setOpenDialog] = useState(false);
+ const [openMigration, setOpenMigration] = useState(false);
const gold = useBalance();
@@ -199,7 +232,6 @@ export default function UserInfo() {
const t = useT();
- const [isCollectionOpen, setCollectionOpen] = useState(false);
const [isExportKeyOpen, setExportKeyOpen] = useState(false);
if (!loginSession) return null;
@@ -220,13 +252,12 @@ export default function UserInfo() {
{Number(gold)}
- setCollectionOpen(true)}>
+
{deposit?.replace(/\.0+$/, "") || "0"}
{isCollecting && !canClaim && tip !== 0
? ` - Remaining: ${remainingText}`
: " (-)"}
-
{canClaim && (
)}
{isCollecting && !canClaim && tip !== 0 && isMigratable && (
-
+ {
+ setOpenMigration(true);
+ }}
+ />
)}
{isCollecting && (
stakingStastics()} />
@@ -260,6 +296,24 @@ export default function UserInfo() {
setOpenDialog(false);
}}
/>
+ setOpenMigration(false)}
+ tip={tip}
+ onConfirm={() => {
+ setClaimLoading(true);
+ if (loginSession.publicKey) {
+ requestMigrationTx({
+ variables: {
+ publicKey: loginSession.publicKey.toHex("uncompressed"),
+ amount: new Decimal(deposit!).toNumber(),
+ },
+ });
+ }
+
+ setOpenMigration(false);
+ }}
+ />
+ {
+ onClose();
+ }}
+ />
+
+
+
+
+ If you migrate,
+
+
+ the reward claim cycle gets{" "}
+ reset
+
+ and you need to wait 7 days to claim.
+
+
+
+ Also, deposits cannot be withdrawn within 28 days.
+
+
+
+
+
+
+
+
+ );
+}
+
+export default observer(ClaimContent);
diff --git a/src/renderer/views/MigrateCollectionRewardsOverlay/index.tsx b/src/renderer/views/MigrateCollectionRewardsOverlay/index.tsx
new file mode 100644
index 000000000..8f052b639
--- /dev/null
+++ b/src/renderer/views/MigrateCollectionRewardsOverlay/index.tsx
@@ -0,0 +1,23 @@
+import { observer } from "mobx-react";
+import React from "react";
+import { OverlayProps } from "src/utils/types";
+import MigrateContent from "./MigrateContent";
+
+export interface MigrateCollectionRewardsOverlayProps extends OverlayProps {
+ tip: number;
+ onConfirm(): void;
+}
+
+const transifexTags = "v2/views/MigrateCollectionRewardsOverlay";
+
+function MigrateCollectionRewardsOverlay({
+ isOpen,
+ onClose,
+ ...collectionData
+}: MigrateCollectionRewardsOverlayProps) {
+ return (
+
+ );
+}
+
+export default observer(MigrateCollectionRewardsOverlay);