Skip to content

Commit

Permalink
feat: improve ledger usage with solflare
Browse files Browse the repository at this point in the history
  • Loading branch information
icfor committed Apr 16, 2024
1 parent ceb7a05 commit abd1a2b
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 15 deletions.
1 change: 1 addition & 0 deletions public/locales/en/staking.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"subtitle": "Withdraw now",
"title": "Your unstaked $SOL is now withdrawable"
},
"solflareCloseMsg": "If you are using Ledger with Solflare, unlock it, open the Solana app, and enable the <0>necessary setting</0> to sign transactions.",
"stake": "Stake",
"stake desc": "As a token holder, you can utilize our infrastructure by staking your tokens with us",
"stake with us!": "Stake with us!",
Expand Down
1 change: 1 addition & 0 deletions public/locales/zh-CN/staking.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"subtitle": "立即提款",
"title": "您已解除质押的 $SOL 现已可领取"
},
"solflareCloseMsg": "如果您将 Ledger 与 Solflare 结合使用,请将其解锁,打开 Solana 应用程序,然后启用<0>必要的设置</0>来签署交易。",
"stake": "质押",
"stake desc": "作为通证持有人,你可以安心在我们的基础建设上委托质押原生通证",
"stake with us!": "与我们一起质押!",
Expand Down
1 change: 1 addition & 0 deletions public/locales/zh-HK/staking.json
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
"subtitle": "立即提款",
"title": "您已解除質押的 $SOL 現已可領取"
},
"solflareCloseMsg": "如果您將 Ledger 與 Solflare 結合使用,請將其解鎖,打開 Solana 應用程序,然後啟用<0>必要的設定</0>來簽署交易。",
"stake": "質押",
"stake desc": "作為通證持有人,你可以安心在我們的基礎建設上委託質押原生通證",
"stake with us!": "與我們一起質押!",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import {
} from "@src/screens/staking/lib/staking_sdk/utils/storage";
import {
MAX_MEMO,
handleWalletClose,
minimumStakeAmountMap,
stakeAmount,
} from "@src/screens/staking/lib/staking_sdk/wallet_operations";
Expand Down Expand Up @@ -198,7 +199,7 @@ const StakingModal = () => {
subtitle: `${t("stakingModal.success.sub")} 🎉`,
title: t("stakingModal.success.title"),
});
} else if (result.error !== StakeError.None) {
} else if (result.error) {
const handlers: Record<StakeError, () => void> = {
[StakeError.MinimumAmount]: () => {
const minimum = result.coin;
Expand All @@ -207,7 +208,9 @@ const StakingModal = () => {
notEnoughAmountError(t, minimum);
}
},
[StakeError.None]: () => {},
[StakeError.None]: () => {
handleWalletClose(account);
},
[StakeError.NotEnoughGas]: () => {
notEnoughGasError(t);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
} from "@src/screens/staking/lib/staking_sdk/utils/storage";
import {
MAX_MEMO,
handleWalletClose,
unstake,
} from "@src/screens/staking/lib/staking_sdk/wallet_operations";
import { UnstakeError } from "@src/screens/staking/lib/staking_sdk/wallet_operations/base";
Expand Down Expand Up @@ -215,7 +216,9 @@ const UnstakingModal = () => {
});
} else if (unstaked.error) {
const handlers: Record<UnstakeError, () => void> = {
[UnstakeError.None]: () => {},
[UnstakeError.None]: () => {
handleWalletClose(selectedAccount);
},
[UnstakeError.NotEnoughGas]: () => {
notEnoughGasError(t);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ import {
getStakeAccountsForNetwork,
} from "@src/screens/staking/lib/staking_sdk/context/selectors";
import { accountHasRewards } from "@src/screens/staking/lib/staking_sdk/utils/accounts";
import { withdrawnUnstaked } from "@src/screens/staking/lib/staking_sdk/wallet_operations";
import {
handleWalletClose,
withdrawnUnstaked,
} from "@src/screens/staking/lib/staking_sdk/wallet_operations";
import { ClaimRewardsError } from "@src/screens/staking/lib/staking_sdk/wallet_operations/base";

import * as styles from "./claim_rewards_modal.module.scss";
Expand Down Expand Up @@ -147,7 +150,9 @@ const WithdrawUnstakedModal = () => {
});
} else if (withdrawn.error) {
const handlers: Record<ClaimRewardsError, () => void> = {
[ClaimRewardsError.None]: () => {},
[ClaimRewardsError.None]: () => {
handleWalletClose(selectedAccount);
},
[ClaimRewardsError.NotEnoughGas]: () => {
notEnoughGasError(t);
},
Expand Down
34 changes: 26 additions & 8 deletions src/screens/staking/lib/staking_sdk/utils/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ const stakedStorageKey = "hasStaked";
const unstakedStorageKey = "hasUnstaked";

const solanaWithdrawReady = "solanaWithdrawReady";
const solflareCloseNotifiedKey = "solflareCloseNotified";

const isValInLastDay = (val?: null | string) => {
if (!val) return false;

const dateTimestamp = JSON.parse(val);

if (Number.isNaN(dateTimestamp)) return false;

const now = Date.now();

return now - dateTimestamp < 1000 * 60 * 60 * 24;
};

export const getConnectedWallets = (): WalletId[] => {
const connectedWallets = window.localStorage.getItem(walletsStorageKey);
Expand Down Expand Up @@ -61,17 +74,22 @@ export const setHasUnstaked = () =>
export const getSolanaWithdrawNotified = () => {
const val = window.localStorage.getItem(solanaWithdrawReady);

if (!val) return false;

const dateTimestamp = JSON.parse(val);
return isValInLastDay(val);
};

if (Number.isNaN(dateTimestamp)) return false;
export const setSolanaWithdrawNotified = () => {
window.localStorage.setItem(solanaWithdrawReady, JSON.stringify(Date.now()));
};

const now = Date.now();
export const getSolflareCloseNotified = () => {
const val = window.localStorage.getItem(solflareCloseNotifiedKey);

return now - dateTimestamp < 1000 * 60 * 60 * 24;
return isValInLastDay(val);
};

export const setSolanaWithdrawNotified = () => {
window.localStorage.setItem(solanaWithdrawReady, JSON.stringify(Date.now()));
export const setSolflareCloseNotified = () => {
window.localStorage.setItem(
solflareCloseNotifiedKey,
JSON.stringify(Date.now()),
);
};
8 changes: 8 additions & 0 deletions src/screens/staking/lib/staking_sdk/wallet_operations.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { TStakingContext } from "./context";
import type { Account } from "./core";
import type { Coin, StakingNetworkId } from "./core/base";
import { WalletId } from "./core/base";
import { keplrNetworks, leapNetworks } from "./core/cosmos";
Expand Down Expand Up @@ -30,6 +31,7 @@ import {
import {
disconnectPhantom,
disconnectSolflare,
handleSolflareClose,
minimumSolanaStakeAmount,
stakeAmountSolana,
tryToConnectPhantom,
Expand Down Expand Up @@ -189,3 +191,9 @@ export const minimumStakeAmountMap: {
} = {
...minimumSolanaStakeAmount,
};

export const handleWalletClose = (account: Account) => {
if (account.wallet === WalletId.Solflare) {
handleSolflareClose();
}
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ import {
} from "@solana/web3.js";
import Solflare from "@solflare-wallet/sdk";
import BigNumber from "bignumber.js";
import Trans from "next-translate/Trans";

import { toastError } from "@src/components/notification";
import { toastError, toastInfo } from "@src/components/notification";

import type { TStakingContext } from "../context";
import { fetchAccountData, setUserWallet } from "../context/actions";
Expand All @@ -19,7 +20,11 @@ import { ENABLE_TESTNETS, StakingNetworkId, WalletId } from "../core/base";
import { solanaNetworks } from "../core/solana";
import { stakingClient } from "../staking_client";
import { normaliseCoin } from "../utils/coins";
import { addToConnectedWallets } from "../utils/storage";
import {
addToConnectedWallets,
getSolflareCloseNotified,
setSolflareCloseNotified,
} from "../utils/storage";
import type {
StakeOpts,
UnstakeAmount,
Expand Down Expand Up @@ -488,3 +493,31 @@ export const disconnectPhantom = async () => {
await provider.disconnect();
}
};

// Haven't found a way to detect if the user is using Ledger when staking with
// Solflare. This displays a message when detecting that the modal was closed
// without staking (at most once per day).
export const handleSolflareClose = () => {
if (getSolflareCloseNotified()) return;

setSolflareCloseNotified();

toastInfo({
title: (
<Trans
components={[
// No content here since it is added by the i18n library
// eslint-disable-next-line jsx-a11y/anchor-has-content
<a
href="https://support.ledger.com/hc/en-us/articles/4499092909085-Allowing-blind-signing-in-the-Solana-SOL-app?docs=true"
key="0"
rel="noopener noreferrer"
target="_blank"
/>,
]}
i18nKey="solflareCloseMsg"
ns="staking"
/>
),
});
};

0 comments on commit abd1a2b

Please sign in to comment.