Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
358ed56
feat(yields): add YieldEnterModal for staking from asset pages
gomesalexandre Jan 12, 2026
8fa0fd8
wip: yield enter modal polish and code cleanup
gomesalexandre Jan 12, 2026
7843007
Merge remote-tracking branch 'origin/feat_yield_polish' into feat_yie…
gomesalexandre Jan 12, 2026
2e027cc
[skip ci] wip: more yield feats, fixes, and polishes
gomesalexandre Jan 12, 2026
83c7e35
[skip ci] wip: yield cleanup - remove unused translations, naming con…
gomesalexandre Jan 12, 2026
7bea932
[skip ci] wip: fix remaining hardcoded colors, use semantic tokens
gomesalexandre Jan 12, 2026
0623238
[skip ci] chore: yield components cleanup pass
gomesalexandre Jan 12, 2026
14b7524
[skip ci] chore: YieldsList extract tab style constant, fix whiteAlph…
gomesalexandre Jan 12, 2026
8111b55
[skip ci] chore: replace remaining gray/whiteAlpha with semantic tokens
gomesalexandre Jan 12, 2026
5305b6f
wip: yield tab styling cleanup, remove unused variables
gomesalexandre Jan 12, 2026
6916645
feat: cosmos validator improvements - ShapeShift first, fallback APR
gomesalexandre Jan 12, 2026
9452076
refactor: yield asset page improvements
gomesalexandre Jan 12, 2026
a4e4d9d
refactor(yields): cleanup pass - extract component, reuse poll util, …
gomesalexandre Jan 12, 2026
dafa3b8
fix(yields): restore original poll impl, fix button text to show tran…
gomesalexandre Jan 12, 2026
c954a35
fix(yields): refactor YieldEnterModal to use click-per-step execution…
gomesalexandre Jan 12, 2026
89936b5
feat(yields): add provider/validator icon to success state in both mo…
gomesalexandre Jan 12, 2026
ac4fa04
fix(yields): wait for tx confirmation before advancing to next step
gomesalexandre Jan 12, 2026
4d132d8
wip
gomesalexandre Jan 12, 2026
1452d11
wip
gomesalexandre Jan 12, 2026
4326075
wip
gomesalexandre Jan 12, 2026
52c6556
Merge remote-tracking branch 'origin/feat_yield_polish' into feat_yie…
gomesalexandre Jan 12, 2026
3d0121e
fix(yields): mobile layout polish and bug fixes
gomesalexandre Jan 12, 2026
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
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -309,5 +309,6 @@ VITE_FEATURE_KATANA=true

# Yield.xyz Feature Flag
VITE_FEATURE_YIELD_XYZ=false
VITE_FEATURE_YIELDS_PAGE=false
VITE_YIELD_XYZ_API_KEY=06903960-e442-4870-81eb-03ff3ad4c035
VITE_FEATURE_YIELD_MULTI_ACCOUNT=false
1 change: 1 addition & 0 deletions .env.development
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,4 @@ VITE_FEATURE_AVNU_SWAP=true
VITE_FEATURE_NEAR=true
VITE_FEATURE_KATANA=true
VITE_FEATURE_YIELD_XYZ=true
VITE_FEATURE_YIELDS_PAGE=true
2 changes: 1 addition & 1 deletion src/Routes/RoutesCommon.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export const routes: Route[] = [
category: RouteCategory.Featured,
priority: 3,
mobileNav: false,
disable: !getConfig().VITE_FEATURE_YIELD_XYZ,
disable: !getConfig().VITE_FEATURE_YIELD_XYZ || !getConfig().VITE_FEATURE_YIELDS_PAGE,
},
{
path: '/ramp/*',
Expand Down
59 changes: 16 additions & 43 deletions src/assets/translations/en/main.json
Original file line number Diff line number Diff line change
Expand Up @@ -2671,6 +2671,7 @@
"pageSubtitle": "Discover and manage yield opportunities across multiple chains",
"enter": "Enter",
"exit": "Exit",
"enterAsset": "Enter %{asset}",
"yield": "Yield",
"apy": "APY",
"apr": "APR",
Expand All @@ -2682,49 +2683,24 @@
"noYields": "No yield opportunities available",
"connectWallet": "Connect a wallet to view yields",
"stats": "Stats",
"minDeposit": "Min Deposit",
"mechanics": "Mechanics",
"minEnter": "Min Enter",
"rewardSchedule": "Reward Schedule",
"gasToken": "Gas Token",
"transactionSteps": "Transaction Steps",
"stepApprove": "Approve",
"stepApproveDesc": "Approve the token for deposit",
"stepDeposit": "Deposit",
"stepDepositDesc": "Deposit your assets into the strategy",
"stepComplete": "Complete",
"stepCompleteDesc": "Your deposit is complete and earning yield",
"gasFeeNote": "Gas fees are paid in the native token of the network",
"yourInfo": "Your Position",
"activeBalance": "Active Balance",
"entering": "Entering",
"entering": "Entering...",
"exiting": "Exiting...",
"withdrawable": "Withdrawable",
"locked": "Locked",
"enterDisabled": "Enter is currently disabled for this yield opportunity",
"exitDisabled": "Exit is currently disabled for this yield opportunity",
"type": "Type",
"inputToken": "Input Token",
"netApy": "Net APY",
"grossApy": "Gross APY",
"totalValue": "Total Value",
"myPosition": "My Position",
"myPositions": "My Positions",
"myValidatorPosition": "My %{validator} Position",
"vault": "Vault",
"lending": "Lending",
"yourDeposits": "Your Deposits",
"positions": "Positions",
"opportunities": "Opportunities",
"yields": "Yields",
"earnUpTo": "You could earn up to %{apy}% on your balance",
"earnUpToOnBalance": "You could earn up to %{apy} on your balance",
"startEarning": "Start earning",
"maxApy": "Max APY",
"validator": "Validator",
"validatorBreakdown": "Validator Breakdown",
"staked": "Staked",
"exiting": "Exiting",
"entered": "Entered",
"claimable": "Claimable",
"loadingQuote": "Loading Quote...",
"depositing": "Depositing...",
"withdrawing": "Withdrawing...",
"selectValidator": "Select Validator",
"allValidators": "All Validators",
"myValidators": "My Validators",
Expand All @@ -2742,17 +2718,16 @@
"allProviders": "All Providers",
"showAll": "Show All",
"searchValidator": "Search for validator",
"depositYourToken": "Deposit your %{symbol} to start earning yield securely.",
"enterYourToken": "Enter your %{symbol} to start earning yield securely.",
"noActiveValidators": "You don't have any active validators yet.",
"confirming": "Confirming...",
"success": "Success!",
"transactions": "Transactions",
"currentApy": "Current APY",
"estYearlyEarnings": "Est. Yearly Earnings",
"allPositions": "All Positions",
"switch": "Switch",
"supplySymbol": "Supply %{symbol}",
"withdrawSymbol": "Withdraw %{symbol}",
"enterSymbol": "Enter %{symbol}",
"exitSymbol": "Exit %{symbol}",
"claimSymbol": "Claim %{symbol}",
"noActivePositions": "You do not have any active yield positions.",
"connectWalletPositions": "Connect a wallet to view your active yield positions.",
Expand All @@ -2770,7 +2745,7 @@
"assetYields": "%{asset} Yields",
"opportunitiesAvailable": "%{count} opportunities available",
"noYieldsMatchingFilters": "No yields found matching filters.",
"activeDeposits": "Active Deposits",
"activePositions": "Active Positions",
"acrossPositions": "Across %{count} positions",
"availableToEarn": "Available to Earn",
"idleAssetsEarning": "Idle assets that could be earning up to %{apy}% APY",
Expand All @@ -2779,22 +2754,20 @@
"earn": "Earn",
"myBalance": "My Balance",
"providers": "Providers",
"deposit": "Deposit",
"withdraw": "Withdraw",
"successDeposit": "You successfully deposited %{amount} %{symbol}",
"successWithdraw": "You successfully withdrew %{amount} %{symbol}",
"successEnter": "You successfully entered %{amount} %{symbol}",
"successExit": "You successfully exited %{amount} %{symbol}",
"successClaim": "You successfully claimed %{amount} %{symbol}",
"resetAllowance": "Reset Allowance",
"transactionNumber": "Transaction %{number}",
"loading": {
"signInWallet": "Sign in Wallet",
"signNow": "Sign now...",
"waiting": "Waiting",
"done": "Done",
"preparing": "Preparing...",
"failed": "Failed",
"preparingTransaction": "Preparing transaction..."
},
"errors": {
"walletNotConnected": "Wallet not connected",
"unsupportedYieldNetwork": "Unsupported yield network",
"broadcastFailed": "Failed to broadcast transaction",
"transactionFailedTitle": "Transaction failed",
"transactionFailedDescription": "Please try again.",
Expand Down
87 changes: 54 additions & 33 deletions src/components/ReactTable/ReactTable.tsx
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Whitespaces off - fixes annoying JSX warnings re: keys

Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,21 @@ const arrowBackIcon = <ArrowBackIcon />
const arrowForwardIcon = <ArrowForwardIcon />

const CellWrap = <T extends {}>({ cell }: { cell: Cell<T, unknown> }) => {
const cellProps = useMemo(() => cell.getCellProps(), [cell])
const dataLabel = useMemo(() => {
return typeof cell.column.Header === 'string' ? cell.column.Header : undefined
}, [cell.column.Header])
const cellProps = useMemo(() => {
const { key: _key, ...rest } = cell.getCellProps()
return rest
}, [cell])
const dataLabel = useMemo(
() => (typeof cell.column.Header === 'string' ? cell.column.Header : undefined),
[cell.column.Header],
)

return (
<Td
{...cellProps}
data-label={dataLabel}
display={cell.column.display}
textAlign={cell.column.textAlign}
key={cell.column.id}
>
{cell.render('Cell')}
</Td>
Expand Down Expand Up @@ -94,7 +97,10 @@ const RowWrap = <T extends {}>({
onRowLongPress?.(row as Row<T>)
}, defaultLongPressConfig)

const rowProps = useMemo(() => row.getRowProps(), [row])
const rowProps = useMemo(() => {
const { key: _key, ...rest } = row.getRowProps()
return rest
}, [row])

const dataTest = useMemo(() => {
if (!rowDataTestKey) return undefined
Expand Down Expand Up @@ -229,33 +235,48 @@ export const ReactTable = <T extends {}>({
<Table ref={tableRef} variant={variant} size={tableSize} {...tableProps}>
{displayHeaders && (
<Thead>
{headerGroups.map(headerGroup => (
<Tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<Th
{...column.getHeaderProps(column.getSortByToggleProps())}
color='text.subtle'
textAlign={column.textAlign}
display={column.display}
// we need to pass an arg here, so we need an anonymous function wrapper
_hover={{ color: column.canSort ? hoverColor : 'text.subtle' }}
>
<Flex justifyContent={column.justifyContent} alignItems={column.alignItems}>
{column.render('Header')}
<Flex alignItems='center'>
{column.isSorted ? (
column.isSortedDesc ? (
<ArrowDownIcon ml={2} aria-label={translate('common.table.sortedDesc')} />
) : (
<ArrowUpIcon ml={2} aria-label={translate('common.table.sortedAsc')} />
)
) : null}
</Flex>
</Flex>
</Th>
))}
</Tr>
))}
{headerGroups.map(headerGroup => {
const { key: headerGroupKey, ...headerGroupProps } = headerGroup.getHeaderGroupProps()
return (
<Tr key={headerGroupKey} {...headerGroupProps}>
{headerGroup.headers.map(column => {
const { key: columnKey, ...columnProps } = column.getHeaderProps(
column.getSortByToggleProps(),
)
return (
<Th
key={columnKey}
{...columnProps}
color='text.subtle'
textAlign={column.textAlign}
display={column.display}
// we need to pass an arg here, so we need an anonymous function wrapper
_hover={{ color: column.canSort ? hoverColor : 'text.subtle' }}
>
<Flex justifyContent={column.justifyContent} alignItems={column.alignItems}>
{column.render('Header')}
<Flex alignItems='center'>
{column.isSorted ? (
column.isSortedDesc ? (
<ArrowDownIcon
ml={2}
aria-label={translate('common.table.sortedDesc')}
/>
) : (
<ArrowUpIcon
ml={2}
aria-label={translate('common.table.sortedAsc')}
/>
)
) : null}
</Flex>
</Flex>
</Th>
)
})}
</Tr>
)
})}
</Thead>
)}
<Tbody {...tableBodyProps}>{renderedRows}</Tbody>
Expand Down
1 change: 1 addition & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ const validators = {
VITE_FEATURE_ADDRESS_BOOK: bool({ default: false }),
VITE_FEATURE_APP_RATING: bool({ default: false }),
VITE_FEATURE_YIELD_XYZ: bool({ default: false }),
VITE_FEATURE_YIELDS_PAGE: bool({ default: false }),
VITE_YIELD_XYZ_API_KEY: str({ default: '' }),
VITE_YIELD_XYZ_BASE_URL: url({ default: 'https://api.yield.xyz/v1' }),
VITE_FEATURE_YIELD_MULTI_ACCOUNT: bool({ default: false }),
Expand Down
22 changes: 22 additions & 0 deletions src/lib/yieldxyz/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
} from '@shapeshiftoss/caip'
import invert from 'lodash/invert'

import type { ValidatorDto } from './types'
import { YieldNetwork } from './types'

export const CHAIN_ID_TO_YIELD_NETWORK: Partial<Record<ChainId, YieldNetwork>> = {
Expand Down Expand Up @@ -62,6 +63,27 @@ export const SHAPESHIFT_VALIDATOR_LOGO =

export const COSMOS_SHAPESHIFT_FALLBACK_APR = '0.1425'

export const COSMOS_NETWORK_FALLBACK_APR = 0.15

export const SHAPESHIFT_VALIDATOR_NAME = 'ShapeShift DAO'

export const SHAPESHIFT_VALIDATOR: ValidatorDto = {
address: SHAPESHIFT_COSMOS_VALIDATOR_ADDRESS,
name: SHAPESHIFT_VALIDATOR_NAME,
logoURI: SHAPESHIFT_VALIDATOR_LOGO,
preferred: true,
votingPower: 0,
commission: 0.1,
status: 'active',
tvl: '0',
tvlRaw: '0',
rewardRate: {
total: parseFloat(COSMOS_SHAPESHIFT_FALLBACK_APR),
rateType: 'APR',
components: [],
},
}

export const COSMOS_DECIMALS = 6

export const COSMOS_ATOM_NATIVE_STAKING_YIELD_ID = 'cosmos-atom-native-staking'
Expand Down
39 changes: 26 additions & 13 deletions src/lib/yieldxyz/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { ChainId } from '@shapeshiftoss/caip'

import {
COSMOS_NETWORK_FALLBACK_APR,
isSupportedYieldNetwork,
SHAPESHIFT_COSMOS_VALIDATOR_ADDRESS,
YIELD_NETWORK_TO_CHAIN_ID,
Expand All @@ -16,29 +17,29 @@ export const yieldNetworkToChainId = (network: string): ChainId | undefined => {

const TX_TITLE_PATTERNS: [RegExp, string][] = [
[/approv/i, 'Approve'],
[/supply|deposit|enter/i, 'Deposit'],
[/withdraw|exit/i, 'Withdraw'],
[/supply|deposit|enter/i, 'Enter'],
[/withdraw|exit|unstake|undelegate/i, 'Exit'],
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the future we could probably make this better and really use the same verbiage as upstream but for now, things are unified

[/claim/i, 'Claim'],
[/unstake|undelegate/i, 'Unstake'],
[/stake|delegate/i, 'Stake'],
[/stake|delegate/i, 'Enter'],
[/bridge/i, 'Bridge'],
[/swap/i, 'Swap'],
]

// Map of transaction types to user-friendly button labels
// These should match the action verbs shown in the step row (without the asset symbol)
// Yield.xyz uses Enter/Exit terminology consistently
const TX_TYPE_TO_LABEL: Record<string, string> = {
APPROVE: 'Approve',
APPROVAL: 'Approve',
DELEGATE: 'Stake', // Monad uses DELEGATE for staking
UNDELEGATE: 'Unstake', // Monad uses UNDELEGATE for unstaking
STAKE: 'Stake',
UNSTAKE: 'Unstake',
DEPOSIT: 'Deposit',
WITHDRAW: 'Withdraw',
SUPPLY: 'Deposit',
EXIT: 'Withdraw',
ENTER: 'Deposit',
DELEGATE: 'Enter', // Monad uses DELEGATE for staking
UNDELEGATE: 'Exit', // Monad uses UNDELEGATE for unstaking
STAKE: 'Enter',
UNSTAKE: 'Exit',
DEPOSIT: 'Enter',
WITHDRAW: 'Exit',
SUPPLY: 'Enter',
EXIT: 'Exit',
ENTER: 'Enter',
BRIDGE: 'Bridge',
SWAP: 'Swap',
CLAIM: 'Claim',
Expand Down Expand Up @@ -147,3 +148,15 @@ export const sortValidators = (

export const toUserCurrency = (usdAmount: string | number, rate: string | number): string =>
bnOrZero(usdAmount).times(rate).toFixed()

export const ensureValidatorApr = (validator: ValidatorDto): ValidatorDto =>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Does what it says on the name!

validator.rewardRate?.total
? validator
: {
...validator,
rewardRate: {
total: COSMOS_NETWORK_FALLBACK_APR,
rateType: 'APR' as const,
components: validator.rewardRate?.components ?? [],
},
}
Loading