Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/pink-garlics-see.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stakekit/widget": patch
---

feat: whitelisted validators, hide chain modal prop
5 changes: 5 additions & 0 deletions .changeset/plain-otters-allow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stakekit/widget": patch
---

fix: position list item amount
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,32 @@ const App = () => {
};
```

### Options

```tsx
type SettingsProps = {
apiKey: string;
theme?: ThemeWrapperTheme;
tracking?: {
trackEvent?: (event: TrackEventVal, properties?: Properties) => void;
trackPageView?: (page: TrackPageVal, properties?: Properties) => void;
};
onMountAnimationComplete?: () => void;
externalProviders?: SKExternalProviders;
disableGasCheck?: boolean;
hideNetworkLogo?: boolean;
disableInitLayoutAnimation?: boolean;
disableResizingInputFontSize?: boolean;
disableAutoScrollToTop?: boolean;
language?: Languages;
customTranslations?: RecursivePartial<typeof localResources>;
tokensForEnabledYieldsOnly?: boolean;
preferredTransactionFormat?: TransactionFormat;
hideChainModal?: boolean;
whitelistedValidatorAddresses?: string[];
};
```

After this is done, you can start using the widget.

## Style customization
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"knip": "^5.50.3",
"turbo": "^2.5.0"
},
"packageManager": "pnpm@10.10.0",
"packageManager": "pnpm@10.11.0",
"pnpm": {
"overrides": {
"@types/react": "19.0.10",
Expand Down
2 changes: 1 addition & 1 deletion packages/widget/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@
"@safe-global/safe-apps-sdk": "^9.1.0",
"@stakekit/api-hooks": "0.0.101",
"@stakekit/common": "^0.0.48",
"@stakekit/rainbowkit": "^2.2.4",
"@stakekit/rainbowkit": "^2.2.5",
"@tanstack/react-query": "^5.74.0",
"@tanstack/react-virtual": "^3.13.6",
"@testing-library/dom": "^10.4.0",
Expand Down
6 changes: 3 additions & 3 deletions packages/widget/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -221,9 +221,9 @@ export type SKAppProps = SettingsProps & (VariantProps | { variant?: never });

export const SKApp = (props: SKAppProps) => {
const variantProps: VariantProps =
!props.variant || props.variant === "default"
? { variant: "default" }
: { variant: props.variant, chainModal: props.chainModal };
props.variant === "zerion"
? { variant: props.variant, chainModal: props.chainModal }
: { variant: props.variant ?? "default" };

const [router] = useState(() =>
createMemoryRouter([{ path: "*", Component: Root }])
Expand Down
1 change: 1 addition & 0 deletions packages/widget/src/components/atoms/link/styles.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ import { style } from "@vanilla-extract/css";

export const link = style({
textDecoration: "none",
display: "inline",
});
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ export const AccountModal = () => {
marginRight="2"
className={avatarContainer}
>
<AvatarComponent address={address as Address} size={24} />
{AvatarComponent && (
<AvatarComponent
address={address as Address}
size={24}
/>
)}
</Box>

<Text className={titleStyle}>
Expand Down
4 changes: 2 additions & 2 deletions packages/widget/src/components/molecules/header/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export const Header = () => {

const { containerRef } = useSyncHeaderHeight();

const { variant } = useSettings();
const { variant, hideChainModal } = useSettings();

const { isConnected, isConnecting, connector } = useSKWallet();

Expand Down Expand Up @@ -112,7 +112,7 @@ export const Header = () => {
animate={{ opacity: 1 }}
transition={{ delay: 0.2, duration: 0.2 }}
>
<ChainModal />
{!hideChainModal && <ChainModal />}

<AccountModal />
</motion.div>
Expand Down
4 changes: 4 additions & 0 deletions packages/widget/src/hooks/api/use-activity-actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getYieldOpportunity } from "@sk-widget/hooks/api/use-yield-opportunity";
import { useWhitelistedValidators } from "@sk-widget/hooks/use-whitelisted-validators";
import { useSKQueryClient } from "@sk-widget/providers/query-client";
import { useSKWallet } from "@sk-widget/providers/sk-wallet";
import {
Expand All @@ -14,6 +15,8 @@ export const useActivityActions = () => {
const { address, network, isLedgerLive } = useSKWallet();
const queryClient = useSKQueryClient();

const whitelistedValidatorAddresses = useWhitelistedValidators();

const query = useInfiniteQuery({
enabled: !!address && !!network,
queryKey: getActionListQueryKey({
Expand Down Expand Up @@ -44,6 +47,7 @@ export const useActivityActions = () => {
yieldId: action.integrationId,
queryClient,
isLedgerLive,
whitelistedValidatorAddresses,
})
.map((yieldData) => ({ actionData: action, yieldData }))
.chainLeft(() => EitherAsync(() => Promise.resolve(null)))
Expand Down
9 changes: 8 additions & 1 deletion packages/widget/src/hooks/api/use-multi-yields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { InitParams } from "@sk-widget/domain/types/init-params";
import type { PositionsData } from "@sk-widget/domain/types/positions";
import { canBeInitialYield } from "@sk-widget/domain/types/stake";
import { useSavedRef } from "@sk-widget/hooks/use-saved-ref";
import { useWhitelistedValidators } from "@sk-widget/hooks/use-whitelisted-validators";
import type { YieldDto } from "@stakekit/api-hooks";
import { type QueryClient, hashKey } from "@tanstack/react-query";
import { useSelector } from "@xstate/react";
Expand Down Expand Up @@ -59,10 +60,13 @@ export const useMultiYields = (yieldIds: string[]) => {

const hashedKey = useMemo(() => hashKey(yieldIds), [yieldIds]);

const whitelistedValidatorAddresses = useWhitelistedValidators();

useEffect(() => {
const sub = multipleYields$({
...argsRef.current,
yieldIds,
whitelistedValidatorAddresses,
})
.pipe(repeat({ delay: () => timer(1000 * 60 * 2) }))
.subscribe({
Expand All @@ -74,7 +78,7 @@ export const useMultiYields = (yieldIds: string[]) => {
});

return () => sub.unsubscribe();
}, [argsRef, yieldIds, hashedKey]);
}, [argsRef, yieldIds, hashedKey, whitelistedValidatorAddresses]);

return useSelector(multiYieldsStore, (state) => {
const map = state.context.data.get(hashedKey);
Expand Down Expand Up @@ -102,6 +106,7 @@ const multipleYields$ = (args: {
isConnected: boolean;
network: SKWallet["network"];
yieldIds: string[];
whitelistedValidatorAddresses: Set<string> | null;
}) =>
merge(
...args.yieldIds.map((v) =>
Expand All @@ -110,6 +115,7 @@ const multipleYields$ = (args: {
isLedgerLive: args.isLedgerLive,
yieldId: v,
queryClient: args.queryClient,
whitelistedValidatorAddresses: args.whitelistedValidatorAddresses,
})
)
)
Expand Down Expand Up @@ -138,6 +144,7 @@ const firstEligibleYield$ = (args: {
initParams: InitParams;
positionsData: PositionsData;
tokenBalanceAmount: BigNumber;
whitelistedValidatorAddresses: Set<string> | null;
}) => {
let defaultYield: YieldDto | null = null;

Expand Down
45 changes: 23 additions & 22 deletions packages/widget/src/hooks/api/use-yield-opportunity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { yieldYieldOpportunity } from "@sk-widget/common/private-api";
import type { YieldDto } from "@stakekit/api-hooks";
import { useWhitelistedValidators } from "@sk-widget/hooks/use-whitelisted-validators";
import type { QueryClient } from "@tanstack/react-query";
import { useQuery } from "@tanstack/react-query";
import { EitherAsync } from "purify-ts";
Expand All @@ -8,6 +8,7 @@ import { useSKWallet } from "../../providers/sk-wallet";
type Params = {
yieldId: string;
isLedgerLive: boolean;
whitelistedValidatorAddresses: Set<string> | null;
signal?: AbortSignal;
};

Expand All @@ -21,13 +22,16 @@ const getKey = (params: Params) => [
export const useYieldOpportunity = (integrationId: string | undefined) => {
const { isLedgerLive } = useSKWallet();

const whitelistedValidatorAddresses = useWhitelistedValidators();

const yieldId = integrationId ?? "";

return useQuery({
queryKey: getKey({ yieldId, isLedgerLive }),
queryKey: getKey({ yieldId, isLedgerLive, whitelistedValidatorAddresses }),
enabled: !!integrationId,
staleTime,
queryFn: ({ signal }) => queryFn({ yieldId, isLedgerLive, signal }),
queryFn: ({ signal }) =>
queryFn({ yieldId, isLedgerLive, signal, whitelistedValidatorAddresses }),
});
};

Expand Down Expand Up @@ -57,6 +61,7 @@ const fn = ({
isLedgerLive,
yieldId,
signal,
whitelistedValidatorAddresses,
}: Params & {
signal?: AbortSignal;
}) =>
Expand All @@ -68,22 +73,18 @@ const fn = ({
},
signal
)
).mapLeft((e) => {
console.log(e);
return new Error("Could not get yield opportunity");
});

export const setYieldOpportunityInCache = ({
yieldDto,
isLedgerLive,
queryClient,
}: {
yieldDto: YieldDto;
isLedgerLive: boolean;
queryClient: QueryClient;
}) => {
queryClient.setQueryData(
getKey({ isLedgerLive, yieldId: yieldDto.id }),
yieldDto
);
};
)
.map((y) =>
whitelistedValidatorAddresses
? {
...y,
validators: y.validators.filter((v) =>
whitelistedValidatorAddresses.has(v.address)
),
}
: y
)
.mapLeft((e) => {
console.log(e);
return new Error("Could not get yield opportunity");
});
6 changes: 6 additions & 0 deletions packages/widget/src/hooks/use-init-params.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { getAndValidateInitParams } from "@sk-widget/hooks/use-init-query-params";
import { useWhitelistedValidators } from "@sk-widget/hooks/use-whitelisted-validators";
import {
type SettingsContextType,
useSettings,
Expand All @@ -22,6 +23,7 @@ export const useInitParams = <T = InitParams>(opts?: {
const { isLedgerLive } = useSKWallet();
const { externalProviders } = useSettings();
const queryClient = useSKQueryClient();
const whitelistedValidatorAddresses = useWhitelistedValidators();

return useQuery({
queryKey,
Expand All @@ -32,6 +34,7 @@ export const useInitParams = <T = InitParams>(opts?: {
isLedgerLive,
queryClient,
externalProviders,
whitelistedValidatorAddresses,
}),
select: opts?.select,
});
Expand Down Expand Up @@ -59,10 +62,12 @@ const fn = ({
isLedgerLive,
queryClient,
externalProviders,
whitelistedValidatorAddresses,
}: {
isLedgerLive: boolean;
queryClient: QueryClient;
externalProviders: SettingsContextType["externalProviders"];
whitelistedValidatorAddresses: Set<string> | null;
}): EitherAsync<Error, InitParams> =>
EitherAsync.liftEither(
getAndValidateInitParams({
Expand All @@ -76,6 +81,7 @@ const fn = ({
isLedgerLive,
yieldId: yId,
queryClient,
whitelistedValidatorAddresses,
})
.map((yieldData) => ({
...val,
Expand Down
14 changes: 14 additions & 0 deletions packages/widget/src/hooks/use-whitelisted-validators.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useSettings } from "@sk-widget/providers/settings";
import { useMemo } from "react";

export const useWhitelistedValidators = () => {
const { whitelistedValidatorAddresses } = useSettings();

return useMemo(
() =>
whitelistedValidatorAddresses
? new Set(whitelistedValidatorAddresses)
: null,
[whitelistedValidatorAddresses]
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const SelectTokenSection = () => {
display="flex"
justifyContent="flex-end"
alignItems="center"
{...(variant === "default" && { marginRight: "2", marginTop: "2" })}
{...(variant !== "zerion" && { marginRight: "2", marginTop: "2" })}
data-rk="stake-token-section-min-max"
>
<Text
Expand Down Expand Up @@ -117,7 +117,7 @@ export const SelectTokenSection = () => {
</Box>
</Box>

{variant === "default" && minStakeAmount}
{variant !== "zerion" && minStakeAmount}

<Box
display="flex"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const SelectYieldSection = () => {
</Box>
) : (
<Box>
{variant === "default" && (
{variant !== "zerion" && (
<Box my="2">
<Text>{t("details.earn")}</Text>
</Box>
Expand Down Expand Up @@ -98,7 +98,7 @@ export const SelectYieldSection = () => {
</Box>
</Box>

{variant === "default" && <SelectYieldRewardDetails />}
{variant !== "zerion" && <SelectYieldRewardDetails />}
</Box>

{variant === "zerion" && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export const SelectYieldRewardDetails = () => {

return (
<Box data-rk="yield-rewards">
{variant === "default" && (
{variant !== "zerion" && (
<Box marginTop="3">
<RewardTokenDetails rewardToken={rewardToken} type="stake" />
</Box>
Expand Down
2 changes: 1 addition & 1 deletion packages/widget/src/pages/details/earn-page/earn.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const EarnPageComponent = () => {
>
<PageContainer>
<Box>
{variant === "default" && <SelectTokenTitle />}
{variant !== "zerion" && <SelectTokenTitle />}

<ZerionChainModal />

Expand Down
Loading