From 92e6bf1287a3f6715d6d9149cdb87810d7c9fea1 Mon Sep 17 00:00:00 2001 From: Petar Todorovic Date: Tue, 3 Jun 2025 15:50:00 +0200 Subject: [PATCH] feat: ledger live usde banner --- .changeset/orange-snakes-stay.md | 5 + package.json | 2 +- .../src/components/atoms/icons/balance.tsx | 17 ++ packages/widget/src/domain/types/tokens.ts | 6 +- .../components/select-token-section/index.tsx | 229 +++++++++++------- .../select-token-section/styles.css.ts | 20 ++ .../src/translation/English/translations.json | 3 +- 7 files changed, 188 insertions(+), 94 deletions(-) create mode 100644 .changeset/orange-snakes-stay.md create mode 100644 packages/widget/src/components/atoms/icons/balance.tsx diff --git a/.changeset/orange-snakes-stay.md b/.changeset/orange-snakes-stay.md new file mode 100644 index 00000000..ae9e9fb9 --- /dev/null +++ b/.changeset/orange-snakes-stay.md @@ -0,0 +1,5 @@ +--- +"@stakekit/widget": patch +--- + +feat: ledger live usde banner diff --git a/package.json b/package.json index 69b389f7..f26d8bfa 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "knip": "^5.57.1", "turbo": "^2.5.3" }, - "packageManager": "pnpm@10.11.0", + "packageManager": "pnpm@10.11.1", "pnpm": { "overrides": { "@types/react": "19.0.10", diff --git a/packages/widget/src/components/atoms/icons/balance.tsx b/packages/widget/src/components/atoms/icons/balance.tsx new file mode 100644 index 00000000..67614113 --- /dev/null +++ b/packages/widget/src/components/atoms/icons/balance.tsx @@ -0,0 +1,17 @@ +export const Balance = () => ( + + + +); diff --git a/packages/widget/src/domain/types/tokens.ts b/packages/widget/src/domain/types/tokens.ts index 05a59ab4..92af25e3 100644 --- a/packages/widget/src/domain/types/tokens.ts +++ b/packages/widget/src/domain/types/tokens.ts @@ -1,3 +1,7 @@ -import type { TokenDto } from "@stakekit/api-hooks"; +import { EvmNetworks, type TokenDto } from "@stakekit/api-hooks"; export type TokenString = `${TokenDto["network"]}-${TokenDto["address"]}`; + +export const isUSDeToken = (token: TokenDto) => + token.network === EvmNetworks.ethereum && + token.address === "0x4c9edd5852cd905f086c759e8383e09bff1e68b3"; diff --git a/packages/widget/src/pages/details/earn-page/components/select-token-section/index.tsx b/packages/widget/src/pages/details/earn-page/components/select-token-section/index.tsx index 53b5cc9a..b57fa750 100644 --- a/packages/widget/src/pages/details/earn-page/components/select-token-section/index.tsx +++ b/packages/widget/src/pages/details/earn-page/components/select-token-section/index.tsx @@ -1,11 +1,20 @@ import { Box, NumberInput, Text } from "@sk-widget/components"; import { ContentLoaderSquare } from "@sk-widget/components/atoms/content-loader"; +import { Balance } from "@sk-widget/components/atoms/icons/balance"; import { MaxButton } from "@sk-widget/components/atoms/max-button"; import * as AmountToggle from "@sk-widget/components/molecules/amount-toggle"; -import { priceTxt } from "@sk-widget/pages/details/earn-page/components/select-token-section/styles.css"; +import { isUSDeToken } from "@sk-widget/domain/types"; +import { + bottomBanner, + bottomBannerBottomRadius, + bottomBannerText, + priceTxt, +} from "@sk-widget/pages/details/earn-page/components/select-token-section/styles.css"; import { useEarnPageContext } from "@sk-widget/pages/details/earn-page/state/earn-page-context"; import { useSettings } from "@sk-widget/providers/settings"; -import { Just } from "purify-ts"; +import { useSKWallet } from "@sk-widget/providers/sk-wallet"; +import clsx from "clsx"; +import { Just, Maybe } from "purify-ts"; import { useTranslation } from "react-i18next"; import { SelectToken } from "./select-token"; import { SelectTokenTitle } from "./title"; @@ -15,6 +24,8 @@ export const SelectTokenSection = () => { const { variant } = useSettings(); + const { isLedgerLive } = useSKWallet(); + const { appLoading, selectedTokenAvailableAmount, @@ -28,6 +39,7 @@ export const SelectTokenSection = () => { stakeMinAmount, symbol, isStakeTokenSameAsGasToken, + selectedToken, } = useEarnPageContext(); const isLoading = appLoading || selectTokenIsLoading; @@ -50,6 +62,18 @@ export const SelectTokenSection = () => { const errorBalance = stakeAmountGreaterThanAvailableAmount; + const showBottomUSDeBanner = Maybe.fromRecord({ + selectedTokenAvailableAmount, + selectedToken, + }) + .filter( + (val) => + isLedgerLive && + val.selectedTokenAvailableAmount.amount.isZero() && + isUSDeToken(val.selectedToken) + ) + .isJust(); + const minStakeAmount = Just([ stakeMinAmount .map((v) => `${t("shared.min")} ${v} ${symbol}`) @@ -82,110 +106,133 @@ export const SelectTokenSection = () => { ) : ( - - {variant === "zerion" && ( - - - {minStakeAmount} - - )} - - - - - - - - - - - - {variant !== "zerion" && minStakeAmount} - + - - - {formattedPrice} - + {variant === "zerion" && ( + + + {minStakeAmount} + + )} + + + + + + + + + + {variant !== "zerion" && minStakeAmount} + - - - {selectedTokenAvailableAmount - .map((v) => - variant === "zerion" ? ( - <> - {t("shared.balance")}:  - - {v.shortFormattedAmount} {v.symbol} - - - ) : ( - - - {({ state }) => ( - - {state === "full" - ? v.fullFormattedAmount - : v.shortFormattedAmount} -  {v.symbol} {t("shared.available")} - - )} - - - ) - ) - .extractNullable()} + + + {formattedPrice} - {!isStakeTokenSameAsGasToken && } + + + + {selectedTokenAvailableAmount + .map((v) => + variant === "zerion" ? ( + <> + {t("shared.balance")}:  + + {v.shortFormattedAmount} {v.symbol} + + + ) : ( + + + {({ state }) => ( + + {state === "full" + ? v.fullFormattedAmount + : v.shortFormattedAmount} +  {v.symbol} {t("shared.available")} + + )} + + + ) + ) + .extractNullable()} + + + + {!isStakeTokenSameAsGasToken && ( + + )} + + + {showBottomUSDeBanner && ( + + + + {t("select_token.usde_banner")} + + + )} ); }; diff --git a/packages/widget/src/pages/details/earn-page/components/select-token-section/styles.css.ts b/packages/widget/src/pages/details/earn-page/components/select-token-section/styles.css.ts index 5df027ce..9d592b2b 100644 --- a/packages/widget/src/pages/details/earn-page/components/select-token-section/styles.css.ts +++ b/packages/widget/src/pages/details/earn-page/components/select-token-section/styles.css.ts @@ -1,5 +1,25 @@ +import { atoms } from "@sk-widget/styles/theme"; import { style } from "@vanilla-extract/css"; export const priceTxt = style({ flexGrow: 999, }); + +export const bottomBannerBottomRadius = style({ + borderBottomLeftRadius: 0, + borderBottomRightRadius: 0, +}); + +export const bottomBanner = style([ + atoms({ borderRadius: "xl" }), + { + borderTopLeftRadius: 0, + borderTopRightRadius: 0, + background: + "linear-gradient(90deg, #4B2921 0%, #723426 25.78%, #994238 59.59%, #7C3C48 100%)", + }, +]); + +export const bottomBannerText = style({ + fontSize: "12px", +}); diff --git a/packages/widget/src/translation/English/translations.json b/packages/widget/src/translation/English/translations.json index 2356c9c0..fd3d0757 100644 --- a/packages/widget/src/translation/English/translations.json +++ b/packages/widget/src/translation/English/translations.json @@ -458,7 +458,8 @@ }, "select_token": { "title": "Select token", - "n_available_opps": "{{count}} available opportunities" + "n_available_opps": "{{count}} available opportunities", + "usde_banner": "Missing USDe balance? Swap now and start earning!" }, "referral_lock": { "title": "Referral check",