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
72 changes: 54 additions & 18 deletions packages/widget/src/domain/types/yields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,23 @@ export type YieldMetadata = Pick<
> & {
provider?: YieldProviderDetails;
};

const knownApiYieldTypes = [
"staking",
"restaking",
"lending",
"vault",
"fixed_yield",
"real_world_asset",
"concentrated_liquidity_pool",
"liquidity_pool",
"liquid_staking",
] as const satisfies ReadonlyArray<ApiYieldType>;

type KnownApiYieldType = (typeof knownApiYieldTypes)[number];
type LocallyDerivedYieldType = "native_staking" | "pooled_staking";
export type ExtendedYieldType = ApiYieldType | LocallyDerivedYieldType;
type KnownExtendedYieldType = KnownApiYieldType | LocallyDerivedYieldType;
export type ExtendedYieldType = KnownExtendedYieldType | "unknown";
type YieldActionType = "enter" | "exit";
type YieldArgumentName = ArgumentFieldDto["name"];

Expand Down Expand Up @@ -77,29 +92,28 @@ export const dashboardYieldCategories = [
] as const satisfies ReadonlyArray<DashboardYieldCategory>;

/**
* Maps every API `YieldType` to exactly one dashboard category. The
* `satisfies Record<ApiYieldType, ...>` guarantees exhaustiveness: a new server
* yield type fails the build here until it is assigned a category. This mirrors
* `getDashboardYieldCategory` (which classifies hydrated yields) but is keyed by
* the API `type` so it can drive `types[]` query filters.
* Maps locally known API yield types to dashboard categories. Unknown future
* API types are intentionally not included in filtered queries because the app
* cannot infer which dashboard category they belong to.
*/
const apiYieldTypeToDashboardCategory = {
staking: "stake",
restaking: "stake",
liquid_staking: "stake",
lending: "defi",
vault: "defi",
fixed_yield: "defi",
concentrated_liquidity_pool: "defi",
liquidity_pool: "defi",
real_world_asset: "rwa",
} as const satisfies Record<ApiYieldType, DashboardYieldCategory>;
} as const satisfies Record<KnownApiYieldType, DashboardYieldCategory>;

export const getApiYieldTypesForDashboardCategory = (
category: DashboardYieldCategory
): ApiYieldType[] =>
): KnownApiYieldType[] =>
(
Object.entries(apiYieldTypeToDashboardCategory) as [
ApiYieldType,
KnownApiYieldType,
DashboardYieldCategory,
][]
)
Expand Down Expand Up @@ -306,6 +320,11 @@ export const getYieldFeePercent = (yieldDto: Yield): number | null => {
export const getYieldLockupPeriod = (yieldDto: Yield) =>
secondsToDays(yieldDto.mechanics.lockupPeriod?.seconds);

const knownApiYieldTypeValues = new Set<string>(knownApiYieldTypes);

const isKnownApiYieldType = (type: string): type is KnownApiYieldType =>
knownApiYieldTypeValues.has(type);

export const getExtendedYieldType = (
yieldDto: YieldBase
): ExtendedYieldType => {
Expand All @@ -317,7 +336,9 @@ export const getExtendedYieldType = (
return "pooled_staking";
}

return yieldDto.mechanics.type;
const type = yieldDto.mechanics.type as string;

return isKnownApiYieldType(type) ? type : "unknown";
};

export const getYieldOutputToken = (yieldDto: YieldBase) =>
Expand All @@ -340,6 +361,7 @@ export const hasYieldBearingOutputToken = (yieldDto: YieldBase) =>

const isStakingYieldType = (yieldType: ExtendedYieldType) =>
yieldType === "staking" ||
yieldType === "liquid_staking" ||
yieldType === "native_staking" ||
yieldType === "pooled_staking";

Expand Down Expand Up @@ -383,6 +405,12 @@ export const getYieldTypeLabels = (
review: t("yield_types.restaking.review"),
cta: t("yield_types.restaking.cta"),
},
liquid_staking: {
type: "liquid_staking",
title: t("yield_types.liquid-staking.title"),
review: t("yield_types.liquid-staking.review"),
cta: t("yield_types.liquid-staking.cta"),
},
fixed_yield: {
type: "fixed_yield",
title: t("yield_types.fixed_yield.title"),
Expand Down Expand Up @@ -419,6 +447,12 @@ export const getYieldTypeLabels = (
review: t("yield_types.pooled_staking.review"),
cta: t("yield_types.pooled_staking.cta"),
},
unknown: {
type: "unknown",
title: "Yield",
review: "Earn",
cta: "Earn",
},
Comment on lines +450 to +455

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Localize the "unknown" fallback labels.

These strings are user-facing, but hardcoding "Yield" / "Earn" bypasses i18n and will show English copy in non-English locales whenever the API returns a future unknown type. Use translation keys here the same way the other yield types do.

As per coding guidelines, "When changing user-facing copy, update both packages/widget/src/translation/English/translations.json and packages/widget/src/translation/French/translations.json".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/widget/src/domain/types/yields.ts` around lines 452 - 457, The
unknown yield fallback in the yield type mapping is hardcoded with user-facing
English copy, so localize it the same way as the other entries in the yields
type definitions. Update the `unknown` object in `yields.ts` to use translation
keys instead of literal `"Yield"` and `"Earn"` values, and add the corresponding
keys and values in both
`packages/widget/src/translation/English/translations.json` and
`packages/widget/src/translation/French/translations.json`.

Source: Coding guidelines

} satisfies YieldTypeLabelsMap;

return map[getExtendedYieldType(yieldDto)];
Expand All @@ -427,14 +461,16 @@ export const getYieldTypeLabels = (
const yieldTypesSortRank: { [Key in ExtendedYieldType]: number } = {
real_world_asset: 1,
staking: 2,
native_staking: 3,
pooled_staking: 4,
restaking: 5,
lending: 6,
vault: 7,
fixed_yield: 8,
liquidity_pool: 9,
concentrated_liquidity_pool: 10,
liquid_staking: 3,
native_staking: 4,
pooled_staking: 5,
restaking: 6,
lending: 7,
vault: 8,
fixed_yield: 9,
liquidity_pool: 10,
concentrated_liquidity_pool: 11,
unknown: 12,
};

export const getYieldTypesSortRank = (yieldDto: YieldBase) =>
Expand Down
13 changes: 10 additions & 3 deletions packages/widget/src/generated/api/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,7 @@ export type Team = {
readonly oavEnabled: boolean;
readonly isMfaEnforced: boolean;
readonly hyperliquidVerifyByClientOrderId: boolean;
readonly unifiedAccountModeEnabled: boolean;
readonly referredBy: string | null;
readonly referralCode: string | null;
};
Expand Down Expand Up @@ -787,6 +788,7 @@ export type YieldProviders =
| "lista"
| "dolomite"
| "midas"
| "concrete"
| "dinari"
| "ondo"
| "superstate"
Expand Down Expand Up @@ -855,7 +857,8 @@ export type PerpActionTypes =
| "approveAgent"
| "approveBuilderFee"
| "updateMargin"
| "setTpAndSl";
| "setTpAndSl"
| "setUnifiedAccount";
export type ProgrammaticPerpReportingTransactionDto = {
readonly id: string;
readonly type:
Expand All @@ -873,7 +876,8 @@ export type ProgrammaticPerpReportingTransactionDto = {
| "ENABLE_DEX_ABSTRACTION"
| "APPROVE_AGENT"
| "UPDATE_MARGIN"
| "SET_TP_AND_SL";
| "SET_TP_AND_SL"
| "SET_USER_ABSTRACTION";
readonly status:
| "CREATED"
| "QUEUED"
Expand Down Expand Up @@ -3305,6 +3309,7 @@ export type ActionDto = {
};
export type ActionGasEstimateDto = {
readonly amount: string | null;
readonly entryReserveEstimate?: string;
readonly token: TokenDto;
readonly gasLimit?: string;
readonly transactions: ReadonlyArray<TransactionGasEstimateDto>;
Expand Down Expand Up @@ -4139,7 +4144,8 @@ export type ProgrammaticReportingControllerGetPerpActions200 = {
| "approveAgent"
| "approveBuilderFee"
| "updateMargin"
| "setTpAndSl";
| "setTpAndSl"
| "setUnifiedAccount";
readonly status:
| "CANCELED"
| "CREATED"
Expand Down Expand Up @@ -5168,6 +5174,7 @@ export type YieldV2ControllerYieldsParams = {
| "lista"
| "dolomite"
| "midas"
| "concrete"
| "dinari"
| "ondo"
| "superstate"
Expand Down
10 changes: 8 additions & 2 deletions packages/widget/src/generated/api/yield.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ export type RewardDto = {
};
readonly yieldSource:
| "staking"
| "liquid_staking"
| "restaking"
| "protocol_incentive"
| "campaign_incentive"
Expand All @@ -257,7 +258,8 @@ export type YieldType =
| "fixed_yield"
| "real_world_asset"
| "concentrated_liquidity_pool"
| "liquidity_pool";
| "liquidity_pool"
| "liquid_staking";
export type RewardSchedule =
| "block"
| "hour"
Expand Down Expand Up @@ -3971,7 +3973,8 @@ export type YieldsControllerGetYieldsParams = {
| "fixed_yield"
| "real_world_asset"
| "concentrated_liquidity_pool"
| "liquidity_pool";
| "liquidity_pool"
| "liquid_staking";
readonly types?: ReadonlyArray<
| "staking"
| "restaking"
Expand All @@ -3981,6 +3984,7 @@ export type YieldsControllerGetYieldsParams = {
| "real_world_asset"
| "concentrated_liquidity_pool"
| "liquidity_pool"
| "liquid_staking"
>;
readonly hasCooldownPeriod?: boolean;
readonly hasWarmupPeriod?: boolean;
Expand Down Expand Up @@ -4428,6 +4432,7 @@ export type TokensControllerGetTokensParams = {
| "real_world_asset"
| "concentrated_liquidity_pool"
| "liquidity_pool"
| "liquid_staking"
>;
readonly offset?: number;
readonly limit?: number;
Expand Down Expand Up @@ -4514,6 +4519,7 @@ export type ActionsControllerGetActionsParams = {
| "real_world_asset"
| "concentrated_liquidity_pool"
| "liquidity_pool"
| "liquid_staking"
>;
readonly network?:
| "ethereum"
Expand Down
1 change: 1 addition & 0 deletions packages/widget/src/hooks/use-yield-meta-info.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ export const useYieldMetaInfo = ({

switch (yieldType) {
case "staking":
case "liquid_staking":
case "native_staking":
case "pooled_staking": {
return {
Expand Down
21 changes: 17 additions & 4 deletions packages/widget/src/translation/English/translations.json
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,7 @@
"staking": "staked",
"staking_ethena_usde": "deposited",
"liquid-staking": "staked",
"liquid_staking": "staked",
"vault": "deposited",
"lending": "supplied",
"restaking": "restaked",
Expand All @@ -474,12 +475,14 @@
"fixed_yield": "deposited",
"real_world_asset": "deposited",
"concentrated_liquidity_pool": "deposited",
"liquidity_pool": "deposited"
"liquidity_pool": "deposited",
"unknown": "earned"
},
"unstake": {
"staking": "unstaked",
"staking_ethena_usde": "withdrawn",
"liquid-staking": "unstaked",
"liquid_staking": "unstaked",
"vault": "withdrawn",
"lending": "withdrawn",
"restaking": "unstaked",
Expand All @@ -488,7 +491,8 @@
"fixed_yield": "withdrawn",
"real_world_asset": "withdrawn",
"concentrated_liquidity_pool": "withdrawn",
"liquidity_pool": "withdrawn"
"liquidity_pool": "withdrawn",
"unknown": "withdrawn"
},
"pending_action": {
"stake": "staked",
Expand Down Expand Up @@ -606,6 +610,11 @@
"review": "Liquid Staking",
"cta": "Stake"
},
"liquid_staking": {
"title": "Liquid Staking",
"review": "Liquid Staking",
"cta": "Stake"
},
"vault": {
"title": "Vault",
"review": "Deposit",
Expand Down Expand Up @@ -645,26 +654,30 @@
"native_staking": "Staked",
"pooled_staking": "Staked",
"liquid-staking": "Liquid staked",
"liquid_staking": "Liquid staked",
"lending": "Deposited",
"vault": "Deposited",
"restaking": "Restaked",
"fixed_yield": "Deposited",
"real_world_asset": "Deposited",
"concentrated_liquidity_pool": "Deposited",
"liquidity_pool": "Deposited"
"liquidity_pool": "Deposited",
"unknown": "Yield"
},
"unstake_label": {
"staking": "Unstake",
"native_staking": "Unstake",
"pooled_staking": "Unstake",
"liquid-staking": "Unstake",
"liquid_staking": "Unstake",
"lending": "Withdraw",
"vault": "Withdraw",
"restaking": "Unstake",
"fixed_yield": "Withdraw",
"real_world_asset": "Withdraw",
"concentrated_liquidity_pool": "Withdraw",
"liquidity_pool": "Withdraw"
"liquidity_pool": "Withdraw",
"unknown": "Manage"
},
"balance_type": {
"active": "Active",
Expand Down
Loading