Skip to content

Commit

Permalink
allow entering multi multisend addresses in the roles v2 setup
Browse files Browse the repository at this point in the history
  • Loading branch information
jfschwarz committed May 30, 2024
1 parent be9fb49 commit eeadbe7
Show file tree
Hide file tree
Showing 13 changed files with 328 additions and 173 deletions.
121 changes: 121 additions & 0 deletions packages/app/src/components/MultiSelectBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import { Grid, makeStyles, Typography } from "@material-ui/core"
import React from "react"
import { colors, ZodiacPaper } from "zodiac-ui-components"
import Creatable from "react-select/creatable"
import { CreatableProps } from "react-select/creatable"
import { GroupBase } from "react-select"

const components = {
DropdownIndicator: null,
}

export interface MultiSelectValues {
label: string
value: string
}

const useStyles = makeStyles((theme) => ({
paperContainer: {
background: "rgba(0, 0, 0, 0.2)",
},
message: {
fontSize: 12,
color: "rgba(244, 67, 54, 1)",
},
}))

const customStyles = {
control: (base: any, state: { isFocused: any }) => ({
...base,
background: "none",
width: "100%",
border: "none",
fontFamily: "Roboto Mono !important",
color: "yellow !important",
boxShadow: state.isFocused ? null : null,
"&:hover": {
border: "none",
},
}),
option: (base: any) => ({
...base,
color: "white",
backgroundColor: "#101010",
cursor: "pointer",
}),
menu: (base: any) => ({
...base,
// override border radius to match the box
borderRadius: 0,
backgroundColor: "#101010",
// kill the gap
marginTop: 0,
}),
menuList: (base: any) => ({
...base,
// kill the white space on first and last option
padding: 0,
}),
ValueContainer: (base: any) => ({
...base,
display: "block",
}),
multiValue: (base: any) => ({
...base,
color: "white !important",
background: colors.tan[300],
"&:hover": {
background: colors.tan[300],
},
"& > div": {
color: `white !important`,
},
"& > div[role=button]:hover": {
cursor: "pointer",
color: "blue",
background: colors.tan[500],
},
}),
}

interface MultiSelectBlockCustomProps
extends CreatableProps<MultiSelectValues, true, GroupBase<MultiSelectValues>> {
invalidText?: string
}

export const MultiSelectBlock: React.FC<MultiSelectBlockCustomProps> = (props) => {
const classes = useStyles()

return (
<Grid container spacing={1} direction="column">
<Grid item>
<ZodiacPaper className={classes.paperContainer} borderStyle="double">
<Creatable
{...props}
components={components}
placeholder="Paste an address and press enter..."
isMulti
isClearable={false}
styles={customStyles}
options={props.options}
theme={(theme) => ({
...theme,
colors: {
...theme.colors,
font: "#101010",
primary25: "#101010",
primary: "#101010",
neutral80: "white",
},
})}
/>
</ZodiacPaper>
</Grid>
{props.invalidText && (
<Grid item>
<Typography className={classes.message}>{props.invalidText}</Typography>
</Grid>
)}
</Grid>
)
}
50 changes: 22 additions & 28 deletions packages/app/src/components/ethereum/Address.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import React from "react";
import { makeStyles, Typography, TypographyProps } from "@material-ui/core";
import { CopyToClipboardBtn } from "@gnosis.pm/safe-react-components";
import { AddressExplorerButton } from "./AddressExplorerButton";
import { shortAddress } from "../../utils/string";
import classNames from "classnames";
import React from "react"
import { makeStyles, Typography, TypographyProps } from "@material-ui/core"
import { CopyToClipboardBtn } from "@gnosis.pm/safe-react-components"
import { AddressExplorerButton } from "./AddressExplorerButton"
import { shortAddress } from "../../utils/string"
import classNames from "classnames"

interface AddressProps {
address: string;
short?: boolean;
hideCopyBtn?: boolean;
hideExplorerBtn?: boolean;
showOnHover?: boolean;
gutterBottom?: boolean;
address: string
short?: boolean
hideCopyBtn?: boolean
hideExplorerBtn?: boolean
showOnHover?: boolean
gutterBottom?: boolean
classes?: {
icon?: string;
container?: string;
};
TypographyProps?: TypographyProps;
icon?: string
container?: string
}
TypographyProps?: TypographyProps
}

const useStyles = makeStyles((theme) => ({
Expand All @@ -41,7 +41,7 @@ const useStyles = makeStyles((theme) => ({
visibility: "initial",
},
},
}));
}))

export const Address = ({
address,
Expand All @@ -53,7 +53,7 @@ export const Address = ({
classes: { icon, container } = {},
TypographyProps,
}: AddressProps) => {
const classes = useStyles();
const classes = useStyles()

return (
<div
Expand All @@ -66,17 +66,11 @@ export const Address = ({
{short ? shortAddress(address) : address}
</Typography>
{hideCopyBtn ? null : (
<CopyToClipboardBtn
textToCopy={address}
className={classNames(icon, "btn")}
/>
<CopyToClipboardBtn textToCopy={address} className={classNames(icon, "btn")} />
)}
{hideExplorerBtn ? null : (
<AddressExplorerButton
address={address}
className={classNames(icon, "btn")}
/>
<AddressExplorerButton address={address} className={classNames(icon, "btn")} />
)}
</div>
);
};
)
}
22 changes: 11 additions & 11 deletions packages/app/src/components/ethereum/AddressExplorerButton.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import React from "react";
import { ExplorerButton } from "@gnosis.pm/safe-react-components";
import { useSafeAppsSDK } from "@gnosis.pm/safe-apps-react-sdk";
import { getExplorerInfo } from "../../utils/explorers";
import React from "react"
import { ExplorerButton } from "@gnosis.pm/safe-react-components"
import { useSafeAppsSDK } from "@gnosis.pm/safe-apps-react-sdk"
import { getExplorerInfo } from "../../utils/explorers"

interface AddressExplorerButtonProps {
className?: string;
address: string;
className?: string
address: string
}

export const AddressExplorerButton = ({
address,
className,
}: AddressExplorerButtonProps) => {
const { safe } = useSafeAppsSDK();
const safeExplorer = getExplorerInfo(safe.chainId, address);
if (!safeExplorer) return null;
return <ExplorerButton explorerUrl={safeExplorer} className={className} />;
};
const { safe } = useSafeAppsSDK()
const safeExplorer = getExplorerInfo(safe.chainId, address)
if (!safeExplorer) return null
return <ExplorerButton explorerUrl={safeExplorer} className={className} />
}
16 changes: 8 additions & 8 deletions packages/app/src/components/ethereum/HashInfo.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { EthHashInfo } from "@gnosis.pm/safe-react-components";
import React from "react";
import { makeStyles } from "@material-ui/core";
import { EthHashInfo } from "@gnosis.pm/safe-react-components"
import React from "react"
import { makeStyles } from "@material-ui/core"

const useStyles = makeStyles((theme) => {
return {
Expand All @@ -27,10 +27,10 @@ const useStyles = makeStyles((theme) => {
fontSize: 14,
},
},
};
});
}
})

export const HashInfo = (props: Parameters<typeof EthHashInfo>[0]) => {
const classes = useStyles();
return <EthHashInfo className={classes.hashInfo} {...props} />;
};
const classes = useStyles()
return <EthHashInfo className={classes.hashInfo} {...props} />
}
36 changes: 15 additions & 21 deletions packages/app/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,14 @@
import React from "react";
import ReactDOM from "react-dom";
import { ThemeProvider } from "styled-components";
import {
CssBaseline,
ThemeProvider as MUIThemeProvider,
} from "@material-ui/core";
import { Loader } from "@gnosis.pm/safe-react-components";
import SafeProvider from "@gnosis.pm/safe-apps-react-sdk";
import App from "./App";
import { Provider } from "react-redux";
import { REDUX_STORE } from "./store";
import { Row } from "./components/layout/Row";
import {
zodiacMuiTheme,
gnosisStyledComponentsTheme,
} from "zodiac-ui-components";
import React from "react"
import ReactDOM from "react-dom"
import { ThemeProvider } from "styled-components"
import { CssBaseline, ThemeProvider as MUIThemeProvider } from "@material-ui/core"
import { Loader } from "@gnosis.pm/safe-react-components"
import SafeProvider from "@gnosis.pm/safe-apps-react-sdk"
import App from "./App"
import { Provider } from "react-redux"
import { REDUX_STORE } from "./store"
import { Row } from "./components/layout/Row"
import { zodiacMuiTheme, gnosisStyledComponentsTheme } from "zodiac-ui-components"

const Main = () => {
return (
Expand All @@ -40,12 +34,12 @@ const Main = () => {
</SafeProvider>
</ThemeProvider>
</MUIThemeProvider>
);
};
)
}

ReactDOM.render(
<React.StrictMode>
<Main />
</React.StrictMode>,
document.getElementById("root")
);
document.getElementById("root"),
)
6 changes: 5 additions & 1 deletion packages/app/src/services/ens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ export const getEnsTextRecord = async (
const nameHash = ethers.utils.namehash(ensName)
const ensRegistryContract = new ethers.Contract(ensRegistry, abiRegistry, provider)
const ensResolverAddress = await ensRegistryContract.resolver(nameHash)
const ensResolverContract = new ethers.Contract(ensResolverAddress, abiPublicResolver, provider)
const ensResolverContract = new ethers.Contract(
ensResolverAddress,
abiPublicResolver,
provider,
)
const record = ensResolverContract.functions.text(nameHash, recordId)
return record
}
Expand Down
14 changes: 9 additions & 5 deletions packages/app/src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ export interface RolesModifierParams {
target: string
multisend: string
}
export interface RolesV2ModifierParams {
target: string
multisend: string[]
}

export interface AMBModuleParams {
amb: string
Expand Down Expand Up @@ -608,7 +612,7 @@ export function deployRolesV2Modifier(
provider: JsonRpcProvider,
safeAddress: string,
chainId: number,
args: RolesModifierParams,
args: RolesV2ModifierParams,
) {
const { target, multisend } = args
const { transaction: deployAndSetupTx, expectedModuleAddress: expectedRolesAddress } =
Expand All @@ -632,23 +636,23 @@ export function deployRolesV2Modifier(

const MULTISEND_SELECTOR = "0x8d80ff0a"
const MULTISEND_UNWRAPPER = "0x93B7fCbc63ED8a3a24B59e1C3e6649D50B7427c0"
const setUnwrapperTx = {
const setUnwrapperTxs = multisend.map((address) => ({
to: rolesContract.address,
data: rolesContract.interface.encodeFunctionData("setTransactionUnwrapper", [
multisend,
address,
MULTISEND_SELECTOR,
MULTISEND_UNWRAPPER,
]),
value: "0",
}
}))

return [
{
...deployAndSetupTx,
value: deployAndSetupTx.value.toHexString(),
},
enableModuleTx,
setUnwrapperTx,
...setUnwrapperTxs,
]
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ export const OZReviewSection: React.FC<OZReviewSectionProps> = ({
<Typography>Voting Token:</Typography>
<Link
target="_blank"
href={`${
EXPLORERS_CONFIG[safe.chainId as NETWORK]
}/token/${token.tokenAddress}`}
href={`${EXPLORERS_CONFIG[safe.chainId as NETWORK]}/token/${
token.tokenAddress
}`}
className={classes.value}
>
{token.tokenAddress}
Expand Down
Loading

0 comments on commit eeadbe7

Please sign in to comment.