Skip to content
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

feat(earn): Add enter amount screen #5399

Merged
merged 47 commits into from May 20, 2024
Merged

Conversation

finnian0826
Copy link
Contributor

@finnian0826 finnian0826 commented May 7, 2024

Description

Add EarnEnterAmount screen.

Test plan

Unit tests added.

Manual tests:

When a user has USDC on arbitrum:

enough.mp4

When a user doesn't have enough USDC on arbitrum:

not-enough.mp4

Clicking the info button:

info.mp4

Related issues

Backwards compatibility

Yes

Network scalability

If a new NetworkId and/or Network are added in the future, the changes in this PR will:

  • Continue to work without code changes, OR trigger a compilation error (guaranteeing we find it when a new network is added)

Copy link

codecov bot commented May 7, 2024

Codecov Report

Attention: Patch coverage is 80.63063% with 43 lines in your changes are missing coverage. Please review.

Project coverage is 86.29%. Comparing base (85a9d0c) to head (b1f5a6d).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #5399      +/-   ##
==========================================
- Coverage   86.35%   86.29%   -0.06%     
==========================================
  Files         755      756       +1     
  Lines       30942    31162     +220     
  Branches     5281     5338      +57     
==========================================
+ Hits        26719    26891     +172     
- Misses       3996     4039      +43     
- Partials      227      232       +5     
Files Coverage Δ
src/analytics/Events.tsx 100.00% <100.00%> (ø)
src/analytics/Properties.tsx 100.00% <ø> (ø)
src/components/TokenIcon.tsx 100.00% <100.00%> (ø)
src/earn/EarnCard.tsx 95.65% <100.00%> (ø)
src/earn/EarnCta.tsx 100.00% <100.00%> (ø)
src/navigator/Screens.tsx 100.00% <100.00%> (ø)
src/send/EnterAmount.tsx 96.22% <100.00%> (+0.01%) ⬆️
src/statsig/constants.ts 100.00% <ø> (ø)
src/earn/prepareTransactions.ts 89.33% <50.00%> (-6.06%) ⬇️
src/earn/EarnEnterAmount.tsx 81.00% <81.00%> (ø)

... and 2 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 85a9d0c...b1f5a6d. Read the comment docs.

disableProceed || (disableBalanceCheck ? !!tokenAmount?.isZero() : !transactionIsPossible)
disableProceed ||
(disableBalanceCheck
? !!tokenAmount?.isZero() || (!!tokenAmount?.lte(token.balance) && !transactionIsPossible)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We want to disable the continue button when checking if the prepared transaction is possible, even if we are disabling the warnings.

Copy link
Contributor

Choose a reason for hiding this comment

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

this is getting super hard to read, either consider breaking this up or leave a comment explaining the different scenarios

@@ -441,14 +465,13 @@ function EnterAmount({
/>
)}

{children}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

With children here, the bottom sheets were acting super weird. Need to go through and double check that this doesn't mess anything else up.

Copy link
Contributor

Choose a reason for hiding this comment

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

Pretty sure this will affect the InLineNotification in the jumpstart screen. I guess one option would be to pass bottomsheets in a separate prop.. Not ideal but should work for now

"info": "This pool is powered by Aave",
"infoBottomSheet": {
"title": "Why this pool?",
"description": "This Aave pool has over $150M TVL and more than 6,000 contributors, indicating strong liquidity and trustworthiness. It also uses USDC as its token and Abritrum as its network, which reduces volatility and ensures users will receive inexpensive gas rates.\n\nAll together this makes it a safe and attractive option with competitive APY, ensuring a beneficial investment opportunity for our users.\n\nYou can explore other Aave pools here.",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The "here" is supposed to be a link, but I'm not sure what it is supposed to link to. Also, this is used as the description param for a bottom sheet so I'm not sure how to format links for translations when it is passed as a param.

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe something like https://app.aave.com/markets/? Would be good to check with product. And re description, can we render this as a content inside the bottom sheet instead of using the existing prop?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Confirmed with John that that link is good so I'll add it in

@finnian0826 finnian0826 marked this pull request as ready for review May 15, 2024 22:07
Copy link
Contributor

@satish-ravi satish-ravi left a comment

Choose a reason for hiding this comment

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

some padding looks off

@@ -1583,6 +1583,8 @@ interface EarnEventsProperties {
[EarnEvents.earn_deposit_complete]: undefined
[EarnEvents.earn_deposit_cancel]: undefined
[EarnEvents.earn_view_pools_press]: undefined
[EarnEvents.earn_enter_amount_info_press]: undefined
[EarnEvents.earn_enter_amount_continue_press]: { userHasFunds: boolean }
Copy link
Contributor

Choose a reason for hiding this comment

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

would be good to include some additional props here like the amount the user entered, tokenId etc.

@@ -441,14 +465,13 @@ function EnterAmount({
/>
)}

{children}
Copy link
Contributor

Choose a reason for hiding this comment

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

Pretty sure this will affect the InLineNotification in the jumpstart screen. I guess one option would be to pass bottomsheets in a separate prop.. Not ideal but should work for now

disableProceed?: boolean
children?: React.ReactNode
ProceedComponent: ComponentType<ProceedComponentProps>
disableBalanceCheck?: boolean
proceedComponentStatic?: boolean
Copy link
Contributor

Choose a reason for hiding this comment

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

can we document what this prop means, doesn't seem super obvious

disableProceed || (disableBalanceCheck ? !!tokenAmount?.isZero() : !transactionIsPossible)
disableProceed ||
(disableBalanceCheck
? !!tokenAmount?.isZero() || (!!tokenAmount?.lte(token.balance) && !transactionIsPossible)
Copy link
Contributor

Choose a reason for hiding this comment

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

this is getting super hard to read, either consider breaking this up or leave a comment explaining the different scenarios

Comment on lines 362 to 365
contentContainerStyle={
proceedComponentStatic
? styles.contentContainer
: { ...styles.contentContainer, flexGrow: 1 }
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
contentContainerStyle={
proceedComponentStatic
? styles.contentContainer
: { ...styles.contentContainer, flexGrow: 1 }
contentContainerStyle=[styles.contentContainer, !proceedComponentStatic && {flexGrow: 1}]

"info": "This pool is powered by Aave",
"infoBottomSheet": {
"title": "Why this pool?",
"description": "This Aave pool has over $150M TVL and more than 6,000 contributors, indicating strong liquidity and trustworthiness. It also uses USDC as its token and Abritrum as its network, which reduces volatility and ensures users will receive inexpensive gas rates.\n\nAll together this makes it a safe and attractive option with competitive APY, ensuring a beneficial investment opportunity for our users.\n\nYou can explore other Aave pools here.",
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe something like https://app.aave.com/markets/? Would be good to check with product. And re description, can we render this as a content inside the bottom sheet instead of using the existing prop?

token={token}
tokenAmount={tokenAmount.minus(token.balance)}
/>
{prepareTransactionsResult && prepareTransactionsResult.type === 'possible' && (
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{prepareTransactionsResult && prepareTransactionsResult.type === 'possible' && (
{prepareTransactionsResult?.type === 'possible' && (

does this work?

src/earn/EarnEnterAmount.tsx Show resolved Hide resolved
@@ -150,10 +154,13 @@ function EnterAmount({
prepareTransactionError,
tokenSelectionDisabled = false,
onPressProceed,
onPressInfo,
onSetTokenAmount,
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
onSetTokenAmount,
onChangeTokenAmount,

@@ -71,10 +72,13 @@ interface Props {
prepareTransactionError?: Error
tokenSelectionDisabled?: boolean
onPressProceed(args: ProceedArgs): void
onPressInfo?(): void
Copy link
Contributor

Choose a reason for hiding this comment

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

is onPressInfo needed in EnterAmount? Seems like it just gets it as a prop and passes in back to proceed component, which can all be done within EarnEnterAmount

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no, I'll update it to just be within the proceed component

Copy link
Contributor Author

Choose a reason for hiding this comment

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

actually, I think to do this I would have to have the EarnProceed function inside EarnEnterAmount, and this causes issues with the token amount state value and also rendering APY.

So I think EarnProceed (which needs access to onPressInfo) needs to be outside of EarnEnterAmount so I'm not sure then how it would have access to onPressInfo. @satish-ravi is there some way to access it from outside the function it is declared without passing as a prop?

Copy link

emerge-tools bot commented May 16, 2024

1 build increased size

Name Version Download Change Install Change Approval
Celo (test)
org.celo.mobile.test
1.85.0 (150) 27.1 MB ⬆️ 13.0 kB (0.05%) 64.5 MB ⬆️ 32.8 kB (0.05%) N/A

Celo (test) 1.85.0 (150)
org.celo.mobile.test

⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 32.8 kB (0.05%)
Total download size change: ⬆️ 13.0 kB (0.05%)

Largest size changes

Item Install Size Change
main.jsbundle ⬆️ 32.8 kB

🛸 Powered by Emerge Tools

token={token}
amountEnteredIn={enteredIn}
onPressProceed={onPressContinue}
onPressInfo={onPressInfo}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Still need to pass this here. I tried having EarnProceed be a const inside of EarnEnterAmount rather than a function outside of it, but this was causing it to re-render everytime the input amount was changed and so the APY was flashing a lot.

@finnian0826
Copy link
Contributor Author

export function usePrepareSupplyTransactions() {
const prepareTransactions = useAsyncCallback(prepareSupplyTransactions, {
onError: (error) => {
Logger.error(TAG, `usePrepareSupplyTransactions: ${error}`)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Logger.error(TAG, `usePrepareSupplyTransactions: ${error}`)
Logger.error(TAG, 'usePrepareSupplyTransactions', error)

so the error is logged with trace, you may need an ensureError potentially

prepareTransactionsResult.transactions.length > 0

const disabled =
!!tokenAmount?.isZero() || (!!tokenAmount?.lte(token.balance) && !transactionIsPossible) // Should disable if the user enters 0 or has enough balance but the transaction is not possible, shouldn't disable if they enter an amount larger than their balance as they will go to add flow
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: this won't be readable in the editor, move the comment to one line above and break it up to multiple lines. would be nice if prettier can do this.

prepareTransactionError,
} = usePrepareSupplyTransactions()

const walletAddress = useSelector(walletAddressSelector) as Address
Copy link
Contributor

Choose a reason for hiding this comment

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

can we avoid the as Address, I think we've been doing a isAddress check where required

Comment on lines 1605 to 1609
tokenAmount: string | null
amountInUsd: string | null
amountEnteredIn: AmountEnteredIn
tokenId: string | null
networkId: string | null
Copy link
Contributor

Choose a reason for hiding this comment

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

do these need to be nulls?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

no, they should all have values, I'll update to not take null


const onPressContinue = ({ tokenAmount, token, amountEnteredIn }: ProceedArgs) => {
ValoraAnalytics.track(EarnEvents.earn_enter_amount_continue_press, {
userHasFunds: token.balance?.gte(tokenAmount),
Copy link
Contributor

Choose a reason for hiding this comment

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

reuse isAmountLessThanBalance

})
})

it('should handle navigating to the deposit bottom sheet', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

can this assert the appropriate bottom sheet was opened?

}
)
})
it('should handle navigating to the add crypto bottom sheet', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

same comment as above

<EarnDepositBottomSheet
forwardedRef={reviewBottomSheetRef}
preparedTransaction={prepareTransactionsResult}
amount={tokenAmount ? tokenAmount.toString() : '0'}
Copy link
Contributor

Choose a reason for hiding this comment

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

tokenAmount should be defined with tx is possible right? You can just add this as another condition to the conditional rendering check above instead of the ternary here.

paddingVertical: Spacing.Thick24,
},
valuesText: {
...typeScale.labelSemiBoldSmall,
Copy link
Contributor

Choose a reason for hiding this comment

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

add color to all text styles

}
const onPressMorePools = () => {
ValoraAnalytics.track(EarnEvents.earn_enter_amount_info_more_pools)
navigate(Screens.WebViewScreen, { uri: 'https://app.aave.com/markets/' })
Copy link
Contributor

Choose a reason for hiding this comment

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

can we move this to the earn_stablecoin_config dynamic config?

import { fetchWithTimeout } from 'src/utils/fetchWithTimeout'
import { publicClient } from 'src/viem'
import { TransactionRequest, prepareTransactions } from 'src/viem/prepareTransactions'
import networkConfig, { networkIdToNetwork } from 'src/web3/networkConfig'
import { Address, encodeFunctionData, isAddress, parseUnits } from 'viem'

const TAG = 'src/earn/prepareTransactions'
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 TAG = 'src/earn/prepareTransactions'
const TAG = 'earn/prepareTransactions'

nit: usually we don't include src in the tags.

@finnian0826 finnian0826 added this pull request to the merge queue May 20, 2024
Merged via the queue into main with commit 7421745 May 20, 2024
16 checks passed
@finnian0826 finnian0826 deleted the finnian0826/earn-enter-amount branch May 20, 2024 21:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants