From 20b1e10c3cce1b66df27011c6e81d14c72c64a92 Mon Sep 17 00:00:00 2001 From: armaniferrante Date: Thu, 22 Apr 2021 22:05:29 -0700 Subject: [PATCH] Display default multisig and format --- package.json | 3 +- src/App.test.tsx | 8 +- src/App.tsx | 67 +++-- src/components/Footer.tsx | 62 ++-- src/components/Header.tsx | 229 +++++++------- src/components/Layout.tsx | 72 ++--- src/components/Multisig.tsx | 478 +++++++++++++++--------------- src/components/Notification.tsx | 18 +- src/components/WalletProvider.tsx | 37 +-- src/idl/index.ts | 388 ++++++++++++------------ src/index.css | 6 +- src/index.tsx | 12 +- src/logo.svg | 1 - src/reportWebVitals.ts | 4 +- src/setupTests.ts | 2 +- src/store/index.ts | 4 +- src/store/reducer.ts | 47 +-- src/utils/idl.ts | 16 +- yarn.lock | 5 + 19 files changed, 733 insertions(+), 726 deletions(-) delete mode 100644 src/logo.svg diff --git a/package.json b/package.json index d9f8b4c..8430998 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ ] }, "devDependencies": { - "gh-pages": "^3.1.0" + "gh-pages": "^3.1.0", + "prettier": "^2.2.1" } } diff --git a/src/App.test.tsx b/src/App.test.tsx index 2a68616..d76787e 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,8 +1,8 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import App from './App'; +import React from "react"; +import { render, screen } from "@testing-library/react"; +import App from "./App"; -test('renders learn react link', () => { +test("renders learn react link", () => { render(); const linkElement = screen.getByText(/learn react/i); expect(linkElement).toBeInTheDocument(); diff --git a/src/App.tsx b/src/App.tsx index 08be7a2..96f8363 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,26 +1,27 @@ -import React from 'react'; -import { Provider } from 'react-redux'; -import { useHistory, useLocation } from 'react-router'; -import { HashRouter, Route } from 'react-router-dom'; -import { SnackbarProvider } from 'notistack'; -import { MuiThemeProvider } from '@material-ui/core/styles'; -import CssBaseline from '@material-ui/core/CssBaseline'; -import { unstable_createMuiStrictModeTheme as createMuiTheme } from '@material-ui/core/styles'; -import { PublicKey } from '@solana/web3.js'; -import { store } from './store'; -import WalletProvider from './components/WalletProvider'; -import Layout from './components/Layout'; -import Multisig from './components/Multisig'; +import React from "react"; +import { Provider } from "react-redux"; +import { useHistory, useLocation } from "react-router"; +import { HashRouter, Route } from "react-router-dom"; +import { SnackbarProvider } from "notistack"; +import { MuiThemeProvider } from "@material-ui/core/styles"; +import CssBaseline from "@material-ui/core/CssBaseline"; +import { unstable_createMuiStrictModeTheme as createMuiTheme } from "@material-ui/core/styles"; +import { PublicKey } from "@solana/web3.js"; +import { store } from "./store"; +import WalletProvider from "./components/WalletProvider"; +import Layout from "./components/Layout"; +import Multisig from "./components/Multisig"; +import { networks } from "./store/reducer"; function App() { const theme = createMuiTheme({ palette: { background: { - default: 'rgb(255,255,255)', + default: "rgb(255,255,255)", }, }, typography: { - fontFamily: ['Source Sans Pro', 'sans-serif'].join(','), + fontFamily: ["Source Sans Pro", "sans-serif"].join(","), }, overrides: {}, }); @@ -29,18 +30,18 @@ function App() { - - - - - - - - + + + + + + + + @@ -48,15 +49,18 @@ function App() { } function MultisigPage() { - return ( - - ); + const { hash } = window.location; + if (hash) { + window.location.href = `/#/${networks.mainnet.multisigUpgradeAuthority!.toString()}`; + } + const multisig = networks.mainnet.multisigUpgradeAuthority; + return ; } export function MultisigInstancePage() { const history = useHistory(); const location = useLocation(); - const path = location.pathname.split('/'); + const path = location.pathname.split("/"); if (path.length !== 2) { history.push(`/multisig`); return <>; @@ -66,5 +70,4 @@ export function MultisigInstancePage() { } } - export default App; diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index d860ca5..17f9906 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,48 +1,46 @@ -import React from 'react'; -import Typography from '@material-ui/core/Typography'; -import Link from '@material-ui/core/Link'; +import React from "react"; +import Typography from "@material-ui/core/Typography"; +import Link from "@material-ui/core/Link"; export default function Footer() { return (
-
+
- +
@@ -61,14 +59,14 @@ function FooterButton(props: FooterButtonProps) { return (
- {label} + {label}
); diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 51b9c2c..30e5b90 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -1,32 +1,28 @@ -import React, { useState, useEffect, ReactElement } from 'react'; -import { useSelector, useDispatch } from 'react-redux'; -import { useHistory } from 'react-router-dom'; -import { useSnackbar } from 'notistack'; -import AppBar from '@material-ui/core/AppBar'; -import Toolbar from '@material-ui/core/Toolbar'; -import Select from '@material-ui/core/Select'; -import Menu from '@material-ui/core/Menu'; -import Link from '@material-ui/core/Link'; -import Typography from '@material-ui/core/Typography'; -import MenuItem from '@material-ui/core/MenuItem'; -import IconButton from '@material-ui/core/IconButton'; -import ExitToAppIcon from '@material-ui/icons/ExitToApp'; -import Button from '@material-ui/core/Button'; -import PersonIcon from '@material-ui/icons/Person'; -import BubbleChartIcon from '@material-ui/icons/BubbleChart'; -import SearchIcon from '@material-ui/icons/Search'; -import { PublicKey } from '@solana/web3.js'; -import { - networks, - State as StoreState, - ActionType, -} from '../store/reducer'; -import { useWallet } from './WalletProvider'; +import React, { useState, useEffect, ReactElement } from "react"; +import { useSelector, useDispatch } from "react-redux"; +import { useHistory } from "react-router-dom"; +import { useSnackbar } from "notistack"; +import AppBar from "@material-ui/core/AppBar"; +import Toolbar from "@material-ui/core/Toolbar"; +import Select from "@material-ui/core/Select"; +import Menu from "@material-ui/core/Menu"; +import Link from "@material-ui/core/Link"; +import Typography from "@material-ui/core/Typography"; +import MenuItem from "@material-ui/core/MenuItem"; +import IconButton from "@material-ui/core/IconButton"; +import ExitToAppIcon from "@material-ui/icons/ExitToApp"; +import Button from "@material-ui/core/Button"; +import PersonIcon from "@material-ui/icons/Person"; +import BubbleChartIcon from "@material-ui/icons/BubbleChart"; +import SearchIcon from "@material-ui/icons/Search"; +import { PublicKey } from "@solana/web3.js"; +import { networks, State as StoreState, ActionType } from "../store/reducer"; +import { useWallet } from "./WalletProvider"; export default function Header() { const { wallet } = useWallet(); - const history = useHistory(); - const [multisigAddress, setMultisigAddress] = useState(''); + const history = useHistory(); + const [multisigAddress, setMultisigAddress] = useState(""); const disabled = !isValidPubkey(multisigAddress); const searchFn = () => { history.push(`/${multisigAddress}`); @@ -35,74 +31,76 @@ export default function Header() {
-
+
- - -
- setMultisigAddress(e.target.value as string)} - onKeyPress={e => { - if (e.key === 'Enter') { - searchFn(); - } - }} - /> - - - -
-
+ +
+ setMultisigAddress(e.target.value as string)} + onKeyPress={(e) => { + if (e.key === "Enter") { + searchFn(); + } + }} + /> + + + +
+
- {!wallet.publicKey ? ( - - ) : ( - - )} + {!wallet.publicKey ? ( + + ) : ( + + )}
@@ -113,19 +111,19 @@ export default function Header() { function SerumLogoButton() { const history = useHistory(); return ( -
history.push('/')}> +
history.push("/")}> @@ -189,24 +187,24 @@ function NetworkSelector() { return (
@@ -215,8 +213,8 @@ function NetworkSelector() { open={Boolean(anchorEl)} onClose={handleClose} style={{ - marginLeft: '12px', - color: 'white', + marginLeft: "12px", + color: "white", }} > {Object.keys(networks).map((n: string) => ( @@ -249,17 +247,17 @@ function UserSelector() { displayEmpty renderValue={() => { return ( - + {wallet.publicKey.toString()} ); }} style={{ - marginLeft: '12px', - width: '150px', + marginLeft: "12px", + width: "150px", }} - onChange={e => { - if (e.target.value === 'disconnect') { + onChange={(e) => { + if (e.target.value === "disconnect") { wallet.disconnect(); } }} @@ -267,7 +265,7 @@ function UserSelector() { - Disconnect + Disconnect @@ -279,7 +277,7 @@ type WalletConnectButtonProps = { }; export function WalletConnectButton( - props: WalletConnectButtonProps, + props: WalletConnectButtonProps ): ReactElement { const { showDisconnect } = useSelector((state: StoreState) => { return { @@ -292,9 +290,9 @@ export function WalletConnectButton( // Wallet connection event listeners. useEffect(() => { - wallet.on('disconnect', () => { - enqueueSnackbar('Disconnected from wallet', { - variant: 'info', + wallet.on("disconnect", () => { + enqueueSnackbar("Disconnected from wallet", { + variant: "info", autoHideDuration: 2500, }); dispatch({ @@ -306,7 +304,7 @@ export function WalletConnectButton( item: {}, }); }); - wallet.on('connect', async () => { + wallet.on("connect", async () => { dispatch({ type: ActionType.CommonWalletDidConnect, item: {}, @@ -321,7 +319,7 @@ export function WalletConnectButton( onClick={() => wallet.disconnect()} > - + Disconnect @@ -332,14 +330,13 @@ export function WalletConnectButton( onClick={() => wallet.connect()} > - + Connect wallet ); } - function isValidPubkey(addr: string): boolean { try { new PublicKey(addr); diff --git a/src/components/Layout.tsx b/src/components/Layout.tsx index 6fa05e2..a847167 100644 --- a/src/components/Layout.tsx +++ b/src/components/Layout.tsx @@ -1,8 +1,8 @@ -import React, { useState, PropsWithChildren } from 'react'; -import Typography from '@material-ui/core/Typography'; -import Button from '@material-ui/core/Button'; -import Header from './Header'; -import Footer from './Footer'; +import React, { useState, PropsWithChildren } from "react"; +import Typography from "@material-ui/core/Typography"; +import Button from "@material-ui/core/Button"; +import Header from "./Header"; +import Footer from "./Footer"; type Props = {}; @@ -11,16 +11,16 @@ export default function Layout(props: PropsWithChildren) { return (
@@ -29,19 +29,19 @@ export default function Layout(props: PropsWithChildren) {
- {window.localStorage.getItem('consent') ? ( -
{props.children}
+ {window.localStorage.getItem("consent") ? ( +
{props.children}
) : ( { - window.localStorage.setItem('consent', 'true'); + window.localStorage.setItem("consent", "true"); setRefresh(!refresh); }} /> @@ -56,21 +56,21 @@ function RiskBar() { return (
- + Multisig is unaudited software. Use at your own risk.
@@ -82,19 +82,19 @@ function RiskDisclosureForm({ onConsent }: { onConsent: () => void }) { return (
-
+
@@ -106,7 +106,7 @@ function RiskDisclosureForm({ onConsent }: { onConsent: () => void }) {
-
+
diff --git a/src/components/Multisig.tsx b/src/components/Multisig.tsx index 7d56a64..23ff96a 100644 --- a/src/components/Multisig.tsx +++ b/src/components/Multisig.tsx @@ -1,72 +1,75 @@ -import React, { useState, useEffect } from 'react'; -import { useHistory } from 'react-router'; -import { useSnackbar } from 'notistack'; -import { encode as encodeBase64 } from 'js-base64'; -import Container from '@material-ui/core/Container'; -import AppBar from '@material-ui/core/AppBar'; -import GavelIcon from '@material-ui/icons/Gavel'; -import DescriptionIcon from '@material-ui/icons/Description'; -import Paper from '@material-ui/core/Paper'; -import SupervisorAccountIcon from '@material-ui/icons/SupervisorAccount'; -import CheckIcon from '@material-ui/icons/Check'; -import ReceiptIcon from '@material-ui/icons/Receipt'; -import RemoveIcon from '@material-ui/icons/Remove'; -import Collapse from '@material-ui/core/Collapse'; -import Toolbar from '@material-ui/core/Toolbar'; -import InfoIcon from '@material-ui/icons/Info'; -import Table from '@material-ui/core/Table'; -import TableHead from '@material-ui/core/TableHead'; -import TableBody from '@material-ui/core/TableBody'; -import TableCell from '@material-ui/core/TableCell'; -import TableRow from '@material-ui/core/TableRow'; -import BuildIcon from '@material-ui/icons/Build'; -import Tooltip from '@material-ui/core/Tooltip'; -import CircularProgress from '@material-ui/core/CircularProgress'; -import Typography from '@material-ui/core/Typography'; -import Card from '@material-ui/core/Card'; -import ExpandLess from '@material-ui/icons/ExpandLess'; -import ExpandMore from '@material-ui/icons/ExpandMore'; -import CardContent from '@material-ui/core/CardContent'; -import TextField from '@material-ui/core/TextField'; -import IconButton from '@material-ui/core/IconButton'; -import Button from '@material-ui/core/Button'; -import DialogContent from '@material-ui/core/DialogContent'; -import DialogContentText from '@material-ui/core/DialogContentText'; -import Dialog from '@material-ui/core/Dialog'; -import DialogTitle from '@material-ui/core/DialogTitle'; -import DialogActions from '@material-ui/core/DialogActions'; -import AddIcon from '@material-ui/icons/Add'; -import List from '@material-ui/core/List'; -import ListItemIcon from '@material-ui/core/ListItemIcon'; -import ListItem from '@material-ui/core/ListItem'; -import ListItemText from '@material-ui/core/ListItemText'; -import CheckCircleIcon from '@material-ui/icons/CheckCircle'; -import BN from 'bn.js'; +import React, { useState, useEffect } from "react"; +import { useHistory } from "react-router"; +import { useSnackbar } from "notistack"; +import { encode as encodeBase64 } from "js-base64"; +import Container from "@material-ui/core/Container"; +import AppBar from "@material-ui/core/AppBar"; +import GavelIcon from "@material-ui/icons/Gavel"; +import DescriptionIcon from "@material-ui/icons/Description"; +import Paper from "@material-ui/core/Paper"; +import SupervisorAccountIcon from "@material-ui/icons/SupervisorAccount"; +import CheckIcon from "@material-ui/icons/Check"; +import ReceiptIcon from "@material-ui/icons/Receipt"; +import RemoveIcon from "@material-ui/icons/Remove"; +import Collapse from "@material-ui/core/Collapse"; +import Toolbar from "@material-ui/core/Toolbar"; +import InfoIcon from "@material-ui/icons/Info"; +import Table from "@material-ui/core/Table"; +import TableHead from "@material-ui/core/TableHead"; +import TableBody from "@material-ui/core/TableBody"; +import TableCell from "@material-ui/core/TableCell"; +import TableRow from "@material-ui/core/TableRow"; +import BuildIcon from "@material-ui/icons/Build"; +import Tooltip from "@material-ui/core/Tooltip"; +import CircularProgress from "@material-ui/core/CircularProgress"; +import Typography from "@material-ui/core/Typography"; +import Card from "@material-ui/core/Card"; +import ExpandLess from "@material-ui/icons/ExpandLess"; +import ExpandMore from "@material-ui/icons/ExpandMore"; +import CardContent from "@material-ui/core/CardContent"; +import TextField from "@material-ui/core/TextField"; +import IconButton from "@material-ui/core/IconButton"; +import Button from "@material-ui/core/Button"; +import DialogContent from "@material-ui/core/DialogContent"; +import DialogContentText from "@material-ui/core/DialogContentText"; +import Dialog from "@material-ui/core/Dialog"; +import DialogTitle from "@material-ui/core/DialogTitle"; +import DialogActions from "@material-ui/core/DialogActions"; +import AddIcon from "@material-ui/icons/Add"; +import List from "@material-ui/core/List"; +import ListItemIcon from "@material-ui/core/ListItemIcon"; +import ListItem from "@material-ui/core/ListItem"; +import ListItemText from "@material-ui/core/ListItemText"; +import CheckCircleIcon from "@material-ui/icons/CheckCircle"; +import BN from "bn.js"; import { Account, PublicKey, SYSVAR_RENT_PUBKEY, SYSVAR_CLOCK_PUBKEY, -} from '@solana/web3.js'; -import * as anchor from '@project-serum/anchor'; -import { useWallet } from './WalletProvider'; -import { ViewTransactionOnExplorerButton } from './Notification'; -import * as idl from '../utils/idl'; +} from "@solana/web3.js"; +import * as anchor from "@project-serum/anchor"; +import { useWallet } from "./WalletProvider"; +import { ViewTransactionOnExplorerButton } from "./Notification"; +import * as idl from "../utils/idl"; +import { networks } from "../store/reducer"; export default function Multisig({ multisig }: { multisig?: PublicKey }) { return (
- -
- -
-
+ +
+ +
+
{multisig && }
); @@ -75,16 +78,17 @@ export default function Multisig({ multisig }: { multisig?: PublicKey }) { function NewMultisigButton() { const [open, setOpen] = useState(false); return ( -
+
setOpen(true)}> - + style={{ + border: "solid 1pt #ccc", + width: "60px", + height: "60px", + borderRadius: "30px", + }} + onClick={() => setOpen(true)} + > + setOpen(false)} />
@@ -97,7 +101,7 @@ export function MultisigInstance({ multisig }: { multisig: PublicKey }) { const [transactions, setTransactions] = useState(null); const [showSignerDialog, setShowSignerDialog] = useState(false); const [showAddTransactionDialog, setShowAddTransactionDialog] = useState( - false, + false ); const [forceRefresh, setForceRefresh] = useState(false); useEffect(() => { @@ -112,28 +116,28 @@ export function MultisigInstance({ multisig }: { multisig: PublicKey }) { }); }, [multisig, multisigClient.account]); useEffect(() => { - multisigClient.account.transaction.all(multisig.toBuffer()).then(txs => { + multisigClient.account.transaction.all(multisig.toBuffer()).then((txs) => { setTransactions(txs); }); }, [multisigClient.account.transaction, multisig, forceRefresh]); useEffect(() => { multisigClient.account.multisig .subscribe(multisig) - .on('change', account => { + .on("change", (account) => { setMultisigAccount(account); }); }, [multisigClient, multisig]); return ( - +
- + {multisigAccount === undefined ? ( -
+
@@ -142,8 +146,8 @@ export function MultisigInstance({ multisig }: { multisig: PublicKey }) { Multisig not found @@ -156,14 +160,14 @@ export function MultisigInstance({ multisig }: { multisig: PublicKey }) { {multisigAccount && ( - {multisig.toString()} | {multisigAccount.threshold.toString()}{' '} + {multisig.toString()} | {multisigAccount.threshold.toString()}{" "} of {multisigAccount.owners.length.toString()} Multisig @@ -180,12 +184,12 @@ export function MultisigInstance({ multisig }: { multisig: PublicKey }) { {transactions === null ? ( -
+
@@ -238,17 +242,15 @@ export function NewMultisigDialog({ const [threshold, setThreshold] = useState(2); // @ts-ignore const zeroAddr = new PublicKey().toString(); - const [participants, setParticipants] = useState([ - zeroAddr, - ]); + const [participants, setParticipants] = useState([zeroAddr]); const _onClose = () => { onClose(); setThreshold(2); setParticipants([zeroAddr, zeroAddr]); }; const createMultisig = async () => { - enqueueSnackbar('Creating multisig', { - variant: 'info', + enqueueSnackbar("Creating multisig", { + variant: "info", }); const multisig = new Account(); // Disc. + threshold + nonce. @@ -258,9 +260,9 @@ export function NewMultisigDialog({ const multisigSize = baseSize + ownerSize; const [, nonce] = await PublicKey.findProgramAddress( [multisig.publicKey.toBuffer()], - multisigClient.programId, + multisigClient.programId ); - const owners = participants.map(p => new PublicKey(p)); + const owners = participants.map((p) => new PublicKey(p)); const tx = await multisigClient.rpc.createMultisig( owners, new BN(threshold), @@ -275,13 +277,13 @@ export function NewMultisigDialog({ await multisigClient.account.multisig.createInstruction( multisig, // @ts-ignore - multisigSize, + multisigSize ), ], - }, + } ); enqueueSnackbar(`Multisig created: ${multisig.publicKey.toString()}`, { - variant: 'success', + variant: "success", action: , }); _onClose(); @@ -300,7 +302,7 @@ export function NewMultisigDialog({ label="Threshold" value={threshold} type="number" - onChange={e => setThreshold(parseInt(e.target.value) as number)} + onChange={(e) => setThreshold(parseInt(e.target.value) as number)} /> {participants.map((p, idx) => ( { + onChange={(e) => { const p = [...participants]; p[idx] = e.target.value; setParticipants(p); }} /> ))} -
+
{ const p = [...participants]; @@ -335,10 +337,10 @@ export function NewMultisigDialog({ type="submit" color="primary" onClick={() => - createMultisig().catch(err => { - const str = err ? err.toString() : ''; + createMultisig().catch((err) => { + const str = err ? err.toString() : ""; enqueueSnackbar(`Error creating multisig: ${str}`, { - variant: 'error', + variant: "error", }); }) } @@ -366,30 +368,30 @@ function TxListItem({ useEffect(() => { multisigClient.account.transaction .subscribe(tx.publicKey) - .on('change', account => { + .on("change", (account) => { setTxAccount(account); }); }, [multisigClient, multisig, tx.publicKey]); const rows = [ { - field: 'Program ID', + field: "Program ID", value: txAccount.programId.toString(), }, { - field: 'Did execute', + field: "Did execute", value: txAccount.didExecute.toString(), }, { - field: 'Instruction data', + field: "Instruction data", value: ( {encodeBase64(txAccount.data)} @@ -397,15 +399,15 @@ function TxListItem({ ), }, { - field: 'Multisig', + field: "Multisig", value: txAccount.multisig.toString(), }, { - field: 'Transaction account', + field: "Transaction account", value: tx.publicKey.toString(), }, { - field: 'Owner set seqno', + field: "Owner set seqno", value: txAccount.ownerSetSeqno.toString(), }, ]; @@ -415,11 +417,11 @@ function TxListItem({ field: owner.toString(), value: txAccount.signers[idx] ? : , }; - }, + } ); const approve = async () => { - enqueueSnackbar('Approving transaction', { - variant: 'info', + enqueueSnackbar("Approving transaction", { + variant: "info", }); await multisigClient.rpc.approve({ accounts: { @@ -428,17 +430,17 @@ function TxListItem({ owner: multisigClient.provider.wallet.publicKey, }, }); - enqueueSnackbar('Transaction approved', { - variant: 'success', + enqueueSnackbar("Transaction approved", { + variant: "success", }); }; const execute = async () => { - enqueueSnackbar('Executing transaction', { - variant: 'info', + enqueueSnackbar("Executing transaction", { + variant: "info", }); const [multisigSigner] = await PublicKey.findProgramAddress( [multisig.toBuffer()], - multisigClient.programId, + multisigClient.programId ); await multisigClient.rpc.executeTransaction({ accounts: { @@ -459,8 +461,8 @@ function TxListItem({ isSigner: false, }), }); - enqueueSnackbar('Transaction executed', { - variant: 'success', + enqueueSnackbar("Transaction executed", { + variant: "success", }); }; return ( @@ -469,25 +471,25 @@ function TxListItem({ {icon(tx, multisigClient)} {ixLabel(tx, multisigClient)} {txAccount.didExecute && ( - + )} {open ? : } -
-
+
+
- + @@ -522,7 +524,7 @@ function TxListItem({ - {rows.map(r => ( + {rows.map((r) => ( {r.field} {r.value} @@ -532,7 +534,7 @@ function TxListItem({
- + @@ -552,10 +554,10 @@ function TxListItem({
{txAccount.ownerSetSeqno !== multisigAccount.ownerSetSeqno && ( -
+
The owner set has changed since this transaction was created @@ -563,7 +565,7 @@ function TxListItem({ )} - + @@ -588,8 +590,8 @@ function ixLabel(tx: any, multisigClient: any) { } if (tx.account.programId.equals(multisigClient.programId)) { const setThresholdSighash = multisigClient.coder.sighash( - 'global', - 'change_threshold', + "global", + "change_threshold" ); if (setThresholdSighash.equals(tx.account.data.slice(0, 8))) { return ( @@ -600,8 +602,8 @@ function ixLabel(tx: any, multisigClient: any) { ); } const setOwnersSighash = multisigClient.coder.sighash( - 'global', - 'set_owners', + "global", + "set_owners" ); if (setOwnersSighash.equals(tx.account.data.slice(0, 8))) { return ( @@ -659,8 +661,8 @@ function SignerDialog({ useEffect(() => { PublicKey.findProgramAddress( [multisig.toBuffer()], - multisigClient.programId, - ).then(addrNonce => setSigner(addrNonce[0].toString())); + multisigClient.programId + ).then((addrNonce) => setSigner(addrNonce[0].toString())); }, [multisig, multisigClient.programId, setSigner]); return ( @@ -669,7 +671,13 @@ function SignerDialog({ Multisig Info - + + {multisig?.equals(networks.mainnet.multisigUpgradeAuthority!) && ( + + This multisig is the upgrade authority for the multisig program + itself. + + )} Program derived address: {signer}. This is the address one should use as the authority for data governed by the multisig. @@ -714,7 +722,7 @@ function AddTransactionDialog({ New Transaction - + Create a new transaction to be signed by the multisig. This transaction will not execute until enough owners have signed the @@ -759,11 +767,11 @@ function ChangeThresholdListItem({ const [open, setOpen] = useState(false); return ( <> - setOpen(open => !open)}> + setOpen((open) => !open)}> - + {open ? : } @@ -791,13 +799,13 @@ function ChangeThresholdListItemDetails({ // @ts-ignore const { enqueueSnackbar } = useSnackbar(); const changeThreshold = async () => { - enqueueSnackbar('Creating change threshold transaction', { - variant: 'info', + enqueueSnackbar("Creating change threshold transaction", { + variant: "info", }); const data = changeThresholdData(multisigClient, threshold); const [multisigSigner] = await PublicKey.findProgramAddress( [multisig.toBuffer()], - multisigClient.programId, + multisigClient.programId ); const accounts = [ { @@ -829,13 +837,13 @@ function ChangeThresholdListItemDetails({ await multisigClient.account.transaction.createInstruction( transaction, // @ts-ignore - txSize, + txSize ), ], - }, + } ); - enqueueSnackbar('Transaction created', { - variant: 'success', + enqueueSnackbar("Transaction created", { + variant: "success", action: , }); didAddTransaction(transaction.publicKey); @@ -844,23 +852,23 @@ function ChangeThresholdListItemDetails({ return (
{ + onChange={(e) => { // @ts-ignore setThreshold(e.target.value); }} /> -
+
@@ -879,11 +887,11 @@ function MultisigSetOwnersListItem({ const [open, setOpen] = useState(false); return ( <> - setOpen(open => !open)}> + setOpen((open) => !open)}> - + {open ? : } @@ -909,19 +917,17 @@ function SetOwnersListItemDetails({ const { multisigClient } = useWallet(); // @ts-ignore const zeroAddr = new PublicKey().toString(); - const [participants, setParticipants] = useState([ - zeroAddr, - ]); + const [participants, setParticipants] = useState([zeroAddr]); const { enqueueSnackbar } = useSnackbar(); const setOwners = async () => { - enqueueSnackbar('Creating setOwners transaction', { - variant: 'info', + enqueueSnackbar("Creating setOwners transaction", { + variant: "info", }); - const owners = participants.map(p => new PublicKey(p)); + const owners = participants.map((p) => new PublicKey(p)); const data = setOwnersData(multisigClient, owners); const [multisigSigner] = await PublicKey.findProgramAddress( [multisig.toBuffer()], - multisigClient.programId, + multisigClient.programId ); const accounts = [ { @@ -953,13 +959,13 @@ function SetOwnersListItemDetails({ await multisigClient.account.transaction.createInstruction( transaction, // @ts-ignore - txSize, + txSize ), ], - }, + } ); - enqueueSnackbar('Transaction created', { - variant: 'success', + enqueueSnackbar("Transaction created", { + variant: "success", action: , }); didAddTransaction(transaction.publicKey); @@ -968,25 +974,25 @@ function SetOwnersListItemDetails({ return (
{participants.map((p, idx) => ( { + onChange={(e) => { const p = [...participants]; p[idx] = e.target.value; setParticipants(p); }} /> ))} -
+
{ const p = [...participants]; @@ -1000,10 +1006,10 @@ function SetOwnersListItemDetails({
@@ -1024,11 +1030,11 @@ function IdlUpgradeListItem({ const [open, setOpen] = useState(false); return ( <> - setOpen(open => !open)}> + setOpen((open) => !open)}> - + {open ? : } @@ -1057,15 +1063,15 @@ function UpgradeIdlListItemDetails({ const { multisigClient } = useWallet(); const { enqueueSnackbar } = useSnackbar(); const createTransactionAccount = async () => { - enqueueSnackbar('Creating transaction', { - variant: 'info', + enqueueSnackbar("Creating transaction", { + variant: "info", }); const programAddr = new PublicKey(programId as string); const bufferAddr = new PublicKey(buffer as string); const idlAddr = await anchor.utils.idlAddress(programAddr); const [multisigSigner] = await PublicKey.findProgramAddress( [multisig.toBuffer()], - multisigClient.programId, + multisigClient.programId ); const data = idl.encodeInstruction({ setBuffer: {} }); const accs = [ @@ -1095,13 +1101,13 @@ function UpgradeIdlListItemDetails({ await multisigClient.account.transaction.createInstruction( transaction, // @ts-ignore - txSize, + txSize ), ], - }, + } ); - enqueueSnackbar('Transaction created', { - variant: 'success', + enqueueSnackbar("Transaction created", { + variant: "success", action: , }); didAddTransaction(transaction.publicKey); @@ -1111,31 +1117,31 @@ function UpgradeIdlListItemDetails({ return (
setProgramId(e.target.value as string)} + onChange={(e) => setProgramId(e.target.value as string)} /> setBuffer(e.target.value as string)} + onChange={(e) => setBuffer(e.target.value as string)} />