Skip to content
This repository has been archived by the owner on Jun 16, 2022. It is now read-only.

LIVE-2162 Solana fixes after initial staking #4969

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
124 changes: 106 additions & 18 deletions cryptoassets.md

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 @@ -49,7 +49,7 @@
"@ledgerhq/hw-transport": "6.27.1",
"@ledgerhq/hw-transport-http": "6.27.1",
"@ledgerhq/hw-transport-node-hid-singleton": "6.27.1",
"@ledgerhq/live-common": "https://github.com/LedgerHQ/ledger-live-common.git#develop",
"@ledgerhq/live-common": "https://github.com/LedgerHQ/ledger-live-common.git#057eeedd36eff56199848d666b1716162370c151",
"@ledgerhq/logs": "6.10.0",
"@ledgerhq/react-ui": "^0.7.5",
"@open-wc/webpack-import-meta-loader": "^0.4.7",
Expand Down
132 changes: 73 additions & 59 deletions src/renderer/families/solana/Delegation/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const Delegation = ({ account }: Props) => {

const onEarnRewards = useCallback(() => {
dispatch(
openModal("MODAL_SOLANA_DELEGATE", {
openModal("MODAL_SOLANA_REWARDS_INFO", {
account,
}),
);
Expand Down Expand Up @@ -90,69 +90,83 @@ const Delegation = ({ account }: Props) => {

return (
<>
<TableContainer mb={6}>
<TableHeader title={<Trans i18nKey="solana.delegation.listHeader" />}>
<Button
id={"account-delegate-button"}
mr={2}
color="palette.primary.main"
small
onClick={onDelegate}
>
<Box horizontal flow={1} alignItems="center">
<DelegateIcon size={12} />
<Box>
<Trans i18nKey="solana.delegation.delegate" />
</Box>
</Box>
</Button>
</TableHeader>
{hasStakes ? (
<>
<Header />
{stakesWithMeta.map(stakeWithMeta => (
<Row
stakeWithMeta={stakeWithMeta}
key={stakeWithMeta.stake.stakeAccAddr}
account={account}
onManageAction={onRedirect}
onExternalLink={onExternalLink}
/>
))}
</>
) : (
<Wrapper horizontal>
<Box style={{ maxWidth: "65%" }}>
<Text ff="Inter|Medium|SemiBold" color="palette.text.shade60" fontSize={4}>
<Trans
i18nKey="solana.delegation.emptyState.description"
values={{ name: account.currency.name }}
/>
</Text>
<Box mt={2}>
<LinkWithExternalIcon
label={<Trans i18nKey="solana.delegation.emptyState.info" />}
onClick={() => openURL(urls.solana.staking)}
/>
</Box>
</Box>
<Box>
<Button primary small onClick={onEarnRewards}>
<Box horizontal flow={1} alignItems="center">
<IconChartLine size={12} />
<Box>
<Trans i18nKey="solana.delegation.emptyState.delegation" />
</Box>
{hasStakes ? (
<TableContainer mb={6}>
<TableHeader title={<Trans i18nKey="solana.delegation.listHeader" />}>
<Button
id={"account-delegate-button"}
mr={2}
color="palette.primary.main"
small
onClick={onDelegate}
>
<Box horizontal flow={1} alignItems="center">
<DelegateIcon size={12} />
<Box>
<Trans i18nKey="solana.delegation.delegate" />
</Box>
</Button>
</Box>
</Wrapper>
)}
</TableContainer>
</Box>
</Button>
</TableHeader>

<Header />
{stakesWithMeta.map(stakeWithMeta => (
<Row
stakeWithMeta={stakeWithMeta}
key={stakeWithMeta.stake.stakeAccAddr}
account={account}
onManageAction={onRedirect}
onExternalLink={onExternalLink}
/>
))}
</TableContainer>
) : null}

{!hasStakes && account.spendableBalance.gt(0) ? (
<TableContainer mb={6}>
<EarnRewardsCTA account={account} onEarnRewards={onEarnRewards} />
</TableContainer>
) : null}
</>
);
};

type EarnRewardsCTAProps = {
account: Account,
onEarnRewards: () => void,
};

function EarnRewardsCTA({ account, onEarnRewards }: EarnRewardsCTAProps) {
return (
<Wrapper horizontal>
<Box style={{ maxWidth: "65%" }}>
<Text ff="Inter|Medium|SemiBold" color="palette.text.shade60" fontSize={4}>
<Trans
i18nKey="solana.delegation.emptyState.description"
values={{ name: account.currency.name }}
/>
</Text>
<Box mt={2}>
<LinkWithExternalIcon
label={<Trans i18nKey="solana.delegation.emptyState.info" />}
onClick={() => openURL(urls.solana.staking)}
/>
</Box>
</Box>
<Box>
<Button primary small onClick={onEarnRewards}>
<Box horizontal flow={1} alignItems="center">
<IconChartLine size={12} />
<Box>
<Trans i18nKey="solana.delegation.emptyState.delegation" />
</Box>
</Box>
</Button>
</Box>
</Wrapper>
);
}

const Delegations = ({ account }: Props) => {
if (!account.solanaResources) return null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function StepValidatorFooter({

return (
<>
<LedgerByFigmentTC />
<LedgerByFigmentTC transaction={transaction} />
<Box horizontal>
<Button mr={1} secondary onClick={onClose}>
<Trans i18nKey="common.cancel" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// @flow
import { getAccountUnit } from "@ledgerhq/live-common/lib/account";
import {
useLedgerFirstShuffledValidators,
useValidators,
useSolanaStakesWithMeta,
} from "@ledgerhq/live-common/lib/families/solana/react";
import invariant from "invariant";
Expand Down Expand Up @@ -49,7 +49,7 @@ export default function StepValidator({

const unit = getAccountUnit(account);

const validators = useLedgerFirstShuffledValidators(account.currency);
const validators = useValidators(account.currency);
const validator = validators.find(v => v.voteAccount === stake.delegation?.voteAccAddr);

if (validator === undefined) {
Expand All @@ -61,6 +61,7 @@ export default function StepValidator({
<TrackPage category="Solana Delegation Deactivate" name="Step Validator" />
{error && <ErrorBanner error={error} />}
<ValidatorRow
disableHover
active
currency={account.currency}
validator={validator}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export function StepValidatorFooter({

return (
<>
<LedgerByFigmentTC />
<LedgerByFigmentTC transaction={transaction} />
<Box horizontal>
<Button mr={1} secondary onClick={onClose}>
<Trans i18nKey="common.cancel" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { getAccountUnit } from "@ledgerhq/live-common/lib/account";
import {
useSolanaStakesWithMeta,
useLedgerFirstShuffledValidators,
useValidators,
} from "@ledgerhq/live-common/lib/families/solana/react";
import invariant from "invariant";
import React from "react";
Expand Down Expand Up @@ -49,7 +49,7 @@ export default function StepValidator({

const unit = getAccountUnit(account);

const validators = useLedgerFirstShuffledValidators(account.currency);
const validators = useValidators(account.currency);
const validator = validators.find(v => v.voteAccount === stake.delegation?.voteAccAddr);

if (validator === undefined) {
Expand All @@ -61,6 +61,7 @@ export default function StepValidator({
<TrackPage category="Solana Delegation Reactivate" name="Step Validator" />
{error && <ErrorBanner error={error} />}
<ValidatorRow
disableHover
active
currency={account.currency}
key={validator.voteAccount}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,19 @@ import LinkWithExternalIcon from "~/renderer/components/LinkWithExternalIcon";
import { useTranslation } from "react-i18next";
import { urls } from "~/config/urls";
import { openURL } from "~/renderer/linking";
import { LEDGER_VALIDATOR_ADDRESS } from "@ledgerhq/live-common/lib/families/solana/utils";
import type { Transaction } from "@ledgerhq/live-common/lib/families/solana/types";

export default function LedgerByFigmentTC() {
type Props = {
transaction: Transaction,
};

export default function LedgerByFigmentTC({ transaction }: Props) {
const { t } = useTranslation();
if (!shouldShowTC(transaction)) {
return null;
}

const openLedgerByFigmentTC = () => openURL(urls.solana.ledgerByFigmentTC);

return (
Expand All @@ -16,3 +26,15 @@ export default function LedgerByFigmentTC() {
/>
);
}

const shouldShowTC = ({ model }: Transaction) => {
switch (model.kind) {
case "stake.createAccount":
return model.uiState.delegate.voteAccAddress === LEDGER_VALIDATOR_ADDRESS;
case "stake.delegate":
return model.uiState.voteAccAddr === LEDGER_VALIDATOR_ADDRESS;
default:
break;
}
return false;
};
43 changes: 25 additions & 18 deletions src/renderer/families/solana/shared/components/ValidatorRow.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@ type Props = {
currency: CryptoCurrency,
validator: ValidatorAppValidator,
active?: boolean,
showStake?: boolean,
onClick?: (v: ValidatorAppValidator) => void,
disableHover?: boolean,
unit: Unit,
};

function SolanaValidatorRow({ validator, active, showStake, onClick, unit, currency }: Props) {
function SolanaValidatorRow({ validator, active, onClick, unit, currency, disableHover }: Props) {
const explorerView = getDefaultExplorerView(currency);

const onExternalLink = useCallback(() => {
Expand All @@ -39,6 +39,7 @@ function SolanaValidatorRow({ validator, active, showStake, onClick, unit, curre

return (
<StyledValidatorRow
disableHover={disableHover ?? false}
onClick={onClick}
key={validator.voteAccount}
validator={{ address: validator.voteAccount }}
Expand All @@ -54,26 +55,22 @@ function SolanaValidatorRow({ validator, active, showStake, onClick, unit, curre
onExternalLink={onExternalLink}
unit={unit}
subtitle={
showStake ? (
<>
<Trans i18nKey="solana.delegation.totalStake"></Trans>
<Text style={{ marginLeft: 5 }}>
{formatCurrencyUnit(unit, new BigNumber(validator.activeStake), {
showCode: true,
})}
</Text>
</>
) : null
<>
<Trans i18nKey="solana.delegation.commission" />
<Text style={{ marginLeft: 5, fontSize: 11 }}>{`${validator.commission} %`}</Text>
</>
}
sideInfo={
<Box ml={5} style={{ flexDirection: "row", alignItems: "center" }}>
<Box>
<Text textAlign="center" ff="Inter|SemiBold" fontSize={2}>
{`${validator.commission} %`}
</Text>
<Text textAlign="center" fontSize={1}>
<Trans i18nKey="solana.delegation.commission" />
<Text textAlign="right" ff="Inter|SemiBold" style={{ fontSize: 13 }}>
{formatCurrencyUnit(unit, new BigNumber(validator.activeStake), {
showCode: true,
})}
</Text>
<TotalStakeTitle>
<Trans i18nKey="solana.delegation.totalStake"></Trans>
</TotalStakeTitle>
</Box>
<Box ml={3}>
<ChosenMark active={active ?? false} />
Expand All @@ -84,14 +81,24 @@ function SolanaValidatorRow({ validator, active, showStake, onClick, unit, curre
);
}

const StyledValidatorRow: ThemedComponent<ValidatorRowProps> = styled(ValidatorRow)`
const StyledValidatorRow: ThemedComponent<ValidatorRowProps & { disableHover: boolean }> = styled(
ValidatorRow,
)`
border-color: transparent;
margin-bottom: 0;
${p => (p.disableHover ? "&:hover { border-color: transparent; }" : "")}
`;

const ChosenMark: ThemedComponent<{ active: boolean }> = styled(Check).attrs(p => ({
color: p.active ? p.theme.colors.palette.primary.main : "transparent",
size: 14,
}))``;

const TotalStakeTitle = styled(Text)`
font-size: 11px;
font-weight: 500;
text-align: right;
color: ${p => p.theme.colors.palette.text.shade60};
`;

export default SolanaValidatorRow;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// @flow
import { getAccountUnit } from "@ledgerhq/live-common/lib/account";
import { useLedgerFirstShuffledValidators } from "@ledgerhq/live-common/lib/families/solana/react";
import { useValidators } from "@ledgerhq/live-common/lib/families/solana/react";
import type { ValidatorAppValidator } from "@ledgerhq/live-common/lib/families/solana/validator-app";
import type { Account, TransactionStatus } from "@ledgerhq/live-common/lib/types";
import invariant from "invariant";
Expand Down Expand Up @@ -32,7 +32,7 @@ const ValidatorField = ({ t, account, onChangeValidator, chosenVoteAccAddr, stat

const unit = getAccountUnit(account);

const validators = useLedgerFirstShuffledValidators(account.currency);
const validators = useValidators(account.currency);

const chosenValidator = useMemo(() => {
if (chosenVoteAccAddr !== null) {
Expand Down Expand Up @@ -64,7 +64,6 @@ const ValidatorField = ({ t, account, onChangeValidator, chosenVoteAccAddr, stat
<ValidatorRow
currency={account.currency}
active={chosenVoteAccAddr === validator.voteAccount}
showStake={validatorIdx !== 0}
onClick={onChangeValidator}
key={validator.voteAccount}
validator={validator}
Expand All @@ -78,7 +77,7 @@ const ValidatorField = ({ t, account, onChangeValidator, chosenVoteAccAddr, stat
<Box p={1}>
<ScrollLoadingList
data={showAll ? validators : [chosenValidator ?? validators[0]]}
style={{ flex: showAll ? "1 0 240px" : "1 0 56px", marginBottom: 0, paddingLeft: 0 }}
style={{ flex: showAll ? "1 0 240px" : "1 0 63px", marginBottom: 0, paddingLeft: 0 }}
renderItem={renderItem}
noResultPlaceholder={
validatorsFiltered.length <= 0 &&
Expand Down
Loading