(Feature) New spending limit modal#1218
(Feature) New spending limit modal#1218fernandomg wants to merge 43 commits intofeature/#413-SpendingLimit-in-appfrom
Conversation
- 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
|
CLA Assistant Lite All Contributors have signed the CLA. |
ESLint Summary View Full Report
[warning] @typescript-eslint/explicit-module-boundary-types
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
|
Travis automatic deployment: |
…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
|
Travis automatic deployment: |
- create - verify existent and inform the user
…dingLimit state issue
| role="button" | ||
| aria-pressed="false" | ||
| tabIndex={0} | ||
| onKeyDown={(e) => { |
There was a problem hiding this comment.
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 = { |
There was a problem hiding this comment.
this could be used in another placer, perhaps moving it to a generic place is a good idea.
There was a problem hiding this comment.
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)` |
There was a problem hiding this comment.
Is this just a disabled state? seems like we should support it in safe-react-components.
| } | ||
| ` | ||
|
|
||
| // TODO: propose refactor in safe-react-components based on this requirements |
There was a problem hiding this comment.
not sure to understand
There was a problem hiding this comment.
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"> |
There was a problem hiding this comment.
can we use Button from src?
| </Field> | ||
| ) | ||
|
|
||
| const Switch = ({ label, name }: { label: string; name: string }): React.ReactElement => ( |
There was a problem hiding this comment.
Can we move this to SRC in the next iteration, we have a checkbox but the radio button is missing.
There was a problem hiding this comment.
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.
|
Travis automatic deployment: |
- used for..of for better readability
|
Is only me having trouble to add ETH allowance? Address 0x000 is not valid. |
It should work, it was me who failed to handle this scenario. Thanks for the catch! |
|
Travis automatic deployment: |
|
Travis automatic deployment: |
this is due to the lack of global variable in the build
|
Travis automatic deployment: |
|
|
||
| // prepare the setAllowance tx | ||
| const web3 = getWeb3() | ||
| const spendingLimit = new web3.eth.Contract(SpendingLimitModule.abi as any, SPENDING_LIMIT_MODULE_ADDRESS) |
There was a problem hiding this comment.
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)
There was a problem hiding this comment.
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' |
There was a problem hiding this comment.
I usually prefer to have import React, { useState } so is explicit that we use useState
There was a problem hiding this comment.
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(() => { |
There was a problem hiding this comment.
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>({ |
There was a problem hiding this comment.
Another hook that is used twice.
I prefer explicit import
| const addressBook = useSelector(getAddressBook) | ||
|
|
||
| const handleScan = (value, closeQrModal) => { | ||
| let scannedAddress = value |
There was a problem hiding this comment.
This can be a oneliner. replace returns a new string.
const scannedAddress = value.startsWith('ethereum:') ? value.replace('ethereum:', '') : value
| const dispatch = useDispatch() | ||
|
|
||
| const [step, setStep] = React.useState<'create' | 'review'>('create') | ||
| const [values, setValues] = React.useState() |
There was a problem hiding this comment.
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: '' }) |
There was a problem hiding this comment.
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)) |
There was a problem hiding this comment.
This function returns type number, isn't it?
There was a problem hiding this comment.
Yes, this was shamelessly copied from the Allowances contract's tests 😬
- also, refactored components for better readability
|
Travis automatic deployment: |
|
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 |

This PR closes #690, by creating modal with form and field validations according to mocks vs current styles.
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.