-
Notifications
You must be signed in to change notification settings - Fork 191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: swap max for non native assets #5923
Conversation
} else if (onPercentOptionClick) { | ||
onPercentOptionClick(option) | ||
} | ||
}, [onPercentOptionClick, onMaxClick, option]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changed the logic slightly, since onPercentOptionClick
is now optional
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since both are now optional, we could end up in a situation where we forget to pass onMaxClick
, and the regular onClick
handler gets fired, which could have very different logic as the max one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solid start. A few initial thoughts:
- We'll want to use the
ASSET_NAMESPACE
constant from thecaip
package, rather than theerc20
string literal. - Whilst the ticket AC does indeed say we only want to handle
erc20
s, we'll also likely want to handlebep20
s (Binance Smart Chain), too. You'll notice non-native BSC assets do not currently support send max in this branch. - We might want to look at using the
isEvmChainId
andisNativeEvmAsset
helpers to achieve this in a more maintainable way. - A few lint issues to fix up 🙏
thanks @0xApotheosis those helper functions are great, and good call about bep20, this should now be handled |
Hey @herbig thanks for the PR! 🍻 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Solid start indeed, thanks a lot for the contribution @herbig!
Following on the great review from @0xApotheosis, I've added a few comments, as this implementation is sane for the most part at runtime but potentially brings some major type safety risks.
From a functional perspective, the max button is indeed available for ERC-20 sell assets:
It looks like the scientific notation is used however, versus precision in the send modal, see:
You can see the send modal implementation for reference BigNumber.toPrecision()
is what you want here:
setValue(SendFormFields.CryptoAmount, cryptoHumanBalance.toPrecision()) |
Fiat max. is also happy.
And confirmed the max. button is only shown for EVM tokens.
@@ -41,15 +45,15 @@ export const PercentOptionsButton: React.FC<MaxButtonProps> = ({ | |||
|
|||
type MaxButtonGroupProps = { | |||
isDisabled?: boolean | |||
onClick: (args: number) => void | |||
onPercentOptionClick?: (args: number) => void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this is a shared component, we absolutely want a discriminated union here - one or the other should always be present: if we ever get to rendering this component, we should have an event handler for it.
} else if (onPercentOptionClick) { | ||
onPercentOptionClick(option) | ||
} | ||
}, [onPercentOptionClick, onMaxClick, option]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since both are now optional, we could end up in a situation where we forget to pass onMaxClick
, and the regular onClick
handler gets fired, which could have very different logic as the max one
const showMax = useMemo( | ||
() => isEvmChainId(fromAssetId(assetId).chainId) && !isNativeEvmAsset(assetId), | ||
[assetId], | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The rendering of the button should be controlled by the presence of percentOptions
, not that of the handler.
I believe a more semantic way to achieve this would be to pass the current default percentOptions
([1]
) array as percentOptions
if this condition is true, and an empty array otherwise.
This way, we would pass this consistently (at least for this component), and have the options rendering logic in a better place.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gomesalexandre is there an instance in the app where we currently display percentOptions that I could see? I couldn't find any but maybe I missed it. My initial thought was that if it wasn't being used the code should just be pulled out altogether and only support the Max button.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
<TradeAssetInput
itself is passed percentOptions
. If you inspect consumers, eventually reaching <TradeInput />
, you'll see this guy:
const percentOptions = [1] |
This is the prop that is controling which percent options are being displayed - showMax
here is effectively redundant, as we're passing 1 (max) as an option from the parent, but then have children programmatically (not) render it
}, [balance, props]) | ||
|
||
const showMax = useMemo( | ||
() => isEvmChainId(fromAssetId(assetId).chainId) && !isNativeEvmAsset(assetId), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also have a isToken
method you may want to take a look at to keep things declarative, it effectively checks for "is non-native asset", which realistically means EVM chain tokens currently, though that could change in the future (as e.g Cosmos SDK chains can have tokens as wells, though we do not support those in the swapper) so the isEvmChainId()
check is definitely welcomed here!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gomesalexandre hmm yeah maybe isToken
is more future thinking, it would be better that if Cosmos support is added later on that the Max button will appear by default
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Either or, that one is fine as-is as we most likely won't support tokens from non-EVM chains for trading in the future but we may. Would prefer it regardless as it reads nicer and is more declarative
@gomesalexandre oh good catch, yeah I didn't see that since I only checked a few assets that would not have triggered scientific notation maybe I'm missing something, but to me it seems both of those screenshots would be wrong. Scientific notation in the But in the Send screen it looks as though you're sending 4.414, which isn't accurate. Also so we're clear, the Max button in |
The scientific notation should never be user-facing, we always want to have either full-precision when applicable, or trimmed decimal places depending on the screens and product spec. For things like sends and swapping, we want to ensure we display the actual amounts that users are going to send out of their wallet. i.e when sending FOX, you can see that the balance (for display purposes only) has trimmed precision, but max. click actually inputs the full-precision amount, with 18 digits in the case of FOX:
Not sure what do you mean here @herbig? Clicking max/percent options will replace the input with the prorated one, with full asset precision, i.e in the screenshot above
That's correct as per our current flow, though definitely not the best UX: we do fees deduction (on native assets only obviously) so trying to send 0.0003 ETH would result in more fees than the actual balance, hence the negative value. |
@herbig - thanks for the PR and work on this issue. @gomesalexandre is going to take it over from here since we haven't heard from you in a bit. I would love to send some FOX tokens your way as a way to thank you for the work on this, if you want to DM me I can get that arranged. Thanks again for your contributions. |
Closing in favor of #5961 |
Description
Brings back the existing Max button in the
TradeAssetInput
component, for ERC20 tokens. This allows users to easily fill the input field with their max balance.This was originally removed to simplify the logic for calculating gas costs, but since ERC20 tokens are not used for paying native gas it is not an issue to bring it back for those.
Pull Request Type
Issue (if applicable)
closes #5828
Risk
This change adds a listener to the Max button, causing it to appear, and fills the input field with the total balance, for non-native (ERC20) tokens only.
This is low-risk, it is unlikely there are unintended consequences to this. Users are generally familiar with the placement and function of a Max button, so should understand what it is doing.
Testing
Engineering
Operations
This is user facing. Testing can be the same as above.
Screenshots (if applicable)