Skip to content

Conversation

@0xPearce
Copy link
Collaborator

@0xPearce 0xPearce commented Nov 28, 2025

  • update the add collateral form to match the design
  • added collateral, prevCollateral, prevHealth, prevDebt and prevLTV to the accordion
  • added input and balance in USD
  • prev and current leverage field coming soon, waiting for llamalend.js (there are 2 tickets for it)
  • refactored getErrorMessage from /loan and /lend int /llamalend
Empty With User Value
Screenshot 2025-12-04 at 16 37 43 Screenshot 2025-12-04 at 16 37 56

Gracefully handle user rejection (unlike my Ex):

Screenshot 2025-12-04 at 16 38 10

@vercel
Copy link

vercel bot commented Nov 28, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
curve-dapp Ready Ready Preview, Comment Dec 13, 2025 3:19pm
curve-dapp-storybook Ready Ready Preview, Comment Dec 13, 2025 3:19pm

import { userMarketValidationSuite } from '@ui-kit/lib/model/query/user-market-validation'
import type { Decimal } from '@ui-kit/utils'

export type UserState = {
Copy link
Collaborator

@0xAlunara 0xAlunara Dec 11, 2025

Choose a reason for hiding this comment

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

Suggested change
export type UserState = {
type QueryData<TUseQuery extends (...args: any[]) => any> = NonNullable<ReturnType<TUseQuery>['data']>
export type UserState = QueryData<typeof useUserState>

Personally I'd rather deduce types implicitly rather than write types as bookkeeping, prevents having to define things twice or more.
We can probably put the QueryData type in a shared places, perhaps in curve-ui-kit\src\lib\queries\types.ts.

Extracting and exporting whatever's returned by queries can be be defined simply as export type UserState = QueryData<typeof useUserState>
Don't forget to remove the Promise<UserState> return type from the queryFn.

Thoughts @DanielSchiavini?

(not a blocker btw, just my personal opinion)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sounds cleaner and more maintanable to me

feat: loan management form remove collateral

const errorMessage = (typeof error === 'object' && error?.message) || (typeof error === 'string' && error)
const showPrevValue = value != null && prevValue != null
const showPrevValue = isSet(value) && isSet(prevValue)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wouldn't const showPrevValue = !!value && !!prevValue have sufficed? 😄
Or something along those lines

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Well if value or prevValue is 0, you still want to treat it as a truthy value. That said, you could argue that we don’t use numbers anymore, only Decimal. This approach is more robust imo

Copy link
Collaborator

Choose a reason for hiding this comment

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

This is incorrect though, cause if value and prevValue are ReactNode, then values like false should also be hidden

@0xAlunara
Copy link
Collaborator

0xAlunara commented Dec 13, 2025

Should we abbreviate the debt and collateral numbers with 'k' and such as we do in a lot of places? These big numbers look a bit ugly. But you could argue that you want the 'exact' data 🤔

Should we also get rid of the 'max removable' helper message? It offers the exact same functionality now as with the old walletBalance that has turned into a llama positionBalance. This holds only for removal I think.

c2tp.eth
image

@0xPearce
Copy link
Collaborator Author

Should we abbreviate the debt and collateral numbers with 'k' and such as we do in a lot of places? These big numbers look a bit ugly. But you could argue that you want the 'exact' data 🤔

Should we also get rid of the 'max removable' helper message? It offers the exact same functionality now as with the old walletBalance that has turned into a llama positionBalance. This holds only for removal I think.

c2tp.eth image

Regarding the collateral, the point was to show the exact data. If I add a small amount of BTC to my position, it could get lost due to rounding, which would make the accordion information not very useful.

Yes, that’s definitely something I wanted to address as well. We currently have three different ways to select the max removable amount: the helper message, the position balance, and the MAX button. We should probably remove one or two of these, perhaps the helper message and the MAX button?

Comment on lines +126 to +130
const value =
values.userCollateral != null &&
state?.collateral != null &&
decimal(new BigNumber(values.userCollateral).plus(state.collateral).toString())
return value ? { value, tokenSymbol: collateralToken?.symbol } : null
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can't we just

Suggested change
const value =
values.userCollateral != null &&
state?.collateral != null &&
decimal(new BigNumber(values.userCollateral).plus(state.collateral).toString())
return value ? { value, tokenSymbol: collateralToken?.symbol } : null
values.userCollateral && state?.collateral && {
value: decimal(new BigNumber(values.userCollateral).plus(state.collateral)),
tokenSymbol: collateralToken?.symbol
}

Note that decimal should support BigNumber imo

state?.collateral != null &&
values.userCollateral != null &&
decimal(
BigNumber.max(new BigNumber(state.collateral).minus(new BigNumber(values.userCollateral)), '0').toString(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
BigNumber.max(new BigNumber(state.collateral).minus(new BigNumber(values.userCollateral)), '0').toString(),
BigNumber.max(0, new BigNumber(state.collateral).minus(new BigNumber(values.userCollateral))),

() => ({ balance, symbol: token?.symbol, loading: isBalanceLoading }),
[balance, isBalanceLoading, token?.symbol],
)}
walletBalance={walletBalance}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Argh this is not a real wallet balance anymore, and tbh LargeTokenInput should not care.
As discussed, for future developments let's try to pass generic ReactNodes

Comment on lines +78 to +80
balance: position ? position.data : balance,
symbol: token?.symbol,
loading: position ? position.isLoading : isBalanceLoading,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
balance: position ? position.data : balance,
symbol: token?.symbol,
loading: position ? position.isLoading : isBalanceLoading,
balance: position?.data ?? balance,
symbol: token?.symbol,
loading: position?.isLoading ?? isBalanceLoading,

tokenAddress: token?.address,
})

const position = positionBalance?.position
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
const position = positionBalance?.position
const { position, tooltip } = positionBalance ?? {}


const errorMessage = (typeof error === 'object' && error?.message) || (typeof error === 'string' && error)
const showPrevValue = value != null && prevValue != null
const showPrevValue = isSet(value) && isSet(prevValue)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is incorrect though, cause if value and prevValue are ReactNode, then values like false should also be hidden

large: 'headingSBold',
} as const satisfies Record<ActionInfoSize, TypographyVariantKey>

const isSet = (v: ReactNode) => v != null && v !== ''
Copy link
Collaborator

Choose a reason for hiding this comment

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

As mentioned below, ReactNodes can be false too

Suggested change
const isSet = (v: ReactNode) => v != null && v !== ''
const isSet = (v: ReactNode) => v || v === 0

*/
tokenSelector?: ReactNode

// TODO: rename to just "balance" because multipurpose now (walletBalance, positionBalance ...)
Copy link
Collaborator

Choose a reason for hiding this comment

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

yeah there is already a balance prop

Suggested change
// TODO: rename to just "balance" because multipurpose now (walletBalance, positionBalance ...)
// TODO: receive a `maxBalance` ReactNode to allow anything to be injected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants