Skip to content
This repository was archived by the owner on Nov 10, 2023. It is now read-only.

(Feature) New spending limit modal#1218

Closed
fernandomg wants to merge 43 commits intofeature/#413-SpendingLimit-in-appfrom
feature/#690-new-SpendingLimit
Closed

(Feature) New spending limit modal#1218
fernandomg wants to merge 43 commits intofeature/#413-SpendingLimit-in-appfrom
feature/#690-new-SpendingLimit

Conversation

@fernandomg
Copy link
Contributor

@fernandomg fernandomg commented Aug 7, 2020

This PR closes #690, by creating modal with form and field validations according to mocks vs current styles.

  • For ease of testing, defaults to an AllowanceModule contract deployed in Rinkeby: https://github.com/gnosis/safe-react/blob/a3b9ee2435e523632609b8324bd5846415d6ec88/src/utils/constants.ts#L18 (this will be removed and should be set in CI variables when the integration branch is merged to development)
  • Users can set a new Spending Limit by selecting the beneficiary from the address book, pick a token from the available in the Safe, and set an arbitrary amount.
  • Also can set a reset time.
  • If, the Spending Limit created already exists (that is: beneficiary<->token, then the user will be prompted with a hard to avoid warning message. Later can -and should- be enhanced).

Note: I'm marking this to be reviewed, as I need feedback for the functionality/flow.

There are snippets of code that need to be refactored, like methods that request module's info, utility functions, etc. that I'll reorganize with the next PR when I build the table of spending limits.

On the safe-react-components side, I recreated some components in the app to cover my needs, but I need to create the issues to solve that in the library.


spending-limit-flow

- marked `isValid` as optional, with default `true` value
- marked `initialValue` as optional
- migrated to hooks for material-ui styles
- migrated to hooks for material-ui styles
- make `label` parametrized and optional, with default value
- make `setIsValidAddress` optional
- migrated to hooks for material-ui styles
…w-SpendingLimit

# Conflicts:
#	src/routes/safe/components/Apps/index.tsx
@github-actions
Copy link

github-actions bot commented Aug 7, 2020

CLA Assistant Lite All Contributors have signed the CLA.

@fernandomg fernandomg self-assigned this Aug 7, 2020
@github-actions
Copy link

github-actions bot commented Aug 7, 2020

ESLint Summary View Full Report

Annotations are provided inline on the Files Changed tab. You can also see all annotations that were generated on the annotations page.

Type Occurrences Fixable
Errors 0 0
Warnings 6 0
Ignored 1 N/A
  • Result: ✅ success

  • Annotations: 6 total


[warning] @typescript-eslint/explicit-module-boundary-types

Require explicit return and argument types on exported functions' and classes' public class methods


Report generated by eslint-plus-action

Also:
- fixed styles
- handled form state while going back and forth between create and review
- had to change `Review` Button as submitting wasn't triggered on the first click.
- also refactored `ScanQRWrapper` so it uses the specified icon
@ghost
Copy link

ghost commented Aug 11, 2020

Travis automatic deployment:
https://pr1218--safereact.review.gnosisdev.com/app

…w-SpendingLimit

# Conflicts:
#	package.json
#	src/routes/safe/components/Apps/index.tsx
#	yarn.lock
- if the module is not enabled it will be enabled on the first tx
- beneficiary is added to the delegate list in the contract
- allowance is set

Still several things to address, like informing the user about an existing allowance, code cleanup
@ghost
Copy link

ghost commented Aug 16, 2020

Travis automatic deployment:
https://pr1218--safereact.review.gnosisdev.com/app

role="button"
aria-pressed="false"
tabIndex={0}
onKeyDown={(e) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

can you extract this to a constant?

import { getNameFromAdbk } from 'src/logic/addressBook/utils'
import AddressBookInput from 'src/routes/safe/components/Balances/SendModal/screens/AddressBookInput'

const KEYCODES = {
Copy link
Contributor

Choose a reason for hiding this comment

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

this could be used in another placer, perhaps moving it to a generic place is a good idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, I'll take this suggestion to move all the generic functions to a utils file, but inside the SpendingLimit/ directory for now

'resetTimeOption resetTimeOption';
`

const YetAnotherButton = styled(GnoButton)`
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this just a disabled state? seems like we should support it in safe-react-components.

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, there's another issue with the SRC Button. By setting its type to submit I need to "double-click" it to actually submit the form.

double-click-to-submit

}
`

// TODO: propose refactor in safe-react-components based on this requirements
Copy link
Contributor

Choose a reason for hiding this comment

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

not sure to understand

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mh! after the refactor that TODO lost its target. 😄

src={QRIcon}
testId="qr-icon"
/>
<button onClick={openQrModal} className={classes.qrCodeBtn} title="Scan QR" data-testid="qr-icon" type="button">
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 use Button from src?

</Field>
)

const Switch = ({ label, name }: { label: string; name: string }): React.ReactElement => (
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 SRC in the next iteration, we have a checkbox but the radio button is missing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just added a more detailed TODO for the Switch (that actually exists in the SRC library, but there are missing props that I need to pass to properly integrate it with RFF).

The RadioButton is in the library, but I added some styles here, that we may need to move over too.

@ghost
Copy link

ghost commented Aug 19, 2020

Travis automatic deployment:
https://pr1218--safereact.review.gnosisdev.com/app

@dasanra
Copy link
Collaborator

dasanra commented Aug 20, 2020

Is only me having trouble to add ETH allowance?

Address 0x000 is not valid.
Is this in scope? If it doesn't maybe we need to remove it from the list

@fernandomg
Copy link
Contributor Author

Is only me having trouble to add ETH allowance?

Address 0x000 is not valid.
Is this in scope? If it doesn't maybe we need to remove it from the list

It should work, it was me who failed to handle this scenario. Thanks for the catch!

@ghost
Copy link

ghost commented Aug 20, 2020

Travis automatic deployment:
https://pr1218--safereact.review.gnosisdev.com/app

@ghost
Copy link

ghost commented Aug 20, 2020

Travis automatic deployment:
https://pr1218--safereact.review.gnosisdev.com/app

this is due to the lack of global variable in the build
@ghost
Copy link

ghost commented Aug 20, 2020

Travis automatic deployment:
https://pr1218--safereact.review.gnosisdev.com/app


// prepare the setAllowance tx
const web3 = getWeb3()
const spendingLimit = new web3.eth.Contract(SpendingLimitModule.abi as any, SPENDING_LIMIT_MODULE_ADDRESS)
Copy link
Collaborator

@dasanra dasanra Aug 20, 2020

Choose a reason for hiding this comment

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

Why create a double instance of the smart contract?

Inside previous if we are doing the exact same new (maybe we should anticipate this general one, because is something we will need regardless of the if result)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure thing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I was expecting to do this later in the integration branch, but given this requirement, I moved the SpendingLimit requests to fetchSafe.

Data now lives in the Safe's store, so it's requested via selectors.

import { makeStyles } from '@material-ui/core/styles'
import { useState } from 'react'
import * as React from 'react'
import React from 'react'
Copy link
Collaborator

Choose a reason for hiding this comment

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

I usually prefer to have import React, { useState } so is explicit that we use useState

Copy link
Contributor Author

@fernandomg fernandomg Aug 20, 2020

Choose a reason for hiding this comment

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

Oh, I prefer the most verbose/explicit way: React.anyHook, so it's easier to follow while reading the code if it's a React's hook or a different one. Whichever the final decision is, this should be added and enforced in a style-guide for sure.


const [pristine, setPristine] = React.useState<boolean>(!initialValues?.beneficiary)

React.useEffect(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would go for explicit import of React hooks

const { initialValues } = useFormState()
const { mutators } = useForm()

const [selectedEntry, setSelectedEntry] = React.useState<{ address: string; name: string } | null>({
Copy link
Collaborator

Choose a reason for hiding this comment

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

Another hook that is used twice.

I prefer explicit import

const addressBook = useSelector(getAddressBook)

const handleScan = (value, closeQrModal) => {
let scannedAddress = value
Copy link
Collaborator

@dasanra dasanra Aug 20, 2020

Choose a reason for hiding this comment

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

This can be a oneliner. replace returns a new string.

const scannedAddress = value.startsWith('ethereum:') ? value.replace('ethereum:', '') : value

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

const dispatch = useDispatch()

const [step, setStep] = React.useState<'create' | 'review'>('create')
const [values, setValues] = React.useState()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also in this occurrences, explicit import of useState is preferred


// TODO: Refactor `delegates` for better performance. This is just to verify allowance works
const safeAddress = useSelector(safeParamAddressFromStateSelector)
const [delegates, setDelegates] = React.useState({ results: [], next: '' })
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also explicit import of useState and useEffect on next line

export const toTokenUnit = (amount: string, decimals: string | number): string =>
new BigNumber(amount).times(`1e${decimals}`).toFixed()

export const currentMinutes = () => Math.floor(Date.now() / (1000 * 60))
Copy link
Collaborator

Choose a reason for hiding this comment

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

This function returns type number, isn't it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, this was shamelessly copied from the Allowances contract's tests 😬

@ghost
Copy link

ghost commented Aug 21, 2020

Travis automatic deployment:
https://pr1218--safereact.review.gnosisdev.com/app

@fernandomg fernandomg requested a review from dasanra August 21, 2020 14:59
@fernandomg
Copy link
Contributor Author

Changes in this PR were already merged into #1261

I've covered all the requirements.

The only exception is for the implicit vs explicit use of React's hook: #1218 (comment) @dasanra

@fernandomg fernandomg closed this Aug 22, 2020
@fernandomg fernandomg deleted the feature/#690-new-SpendingLimit branch August 22, 2020 00:17
@github-actions github-actions bot locked and limited conversation to collaborators Aug 22, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants