From b6a95a7f00d96a6d189bd102b200f3c6429cccb5 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Fri, 10 May 2024 13:31:11 +0700 Subject: [PATCH 01/29] refactor: setup VotingState types update --- apps/multisig/src/domains/referenda/index.ts | 11 +++++++++++ .../layouts/NewTransaction/Vote/VotingForm.tsx | 10 +++++----- .../src/layouts/NewTransaction/Vote/index.tsx | 16 ++++++++++------ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/apps/multisig/src/domains/referenda/index.ts b/apps/multisig/src/domains/referenda/index.ts index e4d8aa85..c34522df 100644 --- a/apps/multisig/src/domains/referenda/index.ts +++ b/apps/multisig/src/domains/referenda/index.ts @@ -22,6 +22,8 @@ export type SplitAbstainVoteParams = { abstain: BN } & SplitVoteParams +export type ConvictionVote = 'Standard' | 'SplitAbstain' + export type VoteDetails = { referendumId?: number details: { @@ -56,6 +58,15 @@ export const defaultVoteDetails: Required = { }, } +export type VoteDetailsState = { + convictionVote: ConvictionVote +} & VoteDetails + +export const defaultVote: VoteDetailsState = { + convictionVote: 'Standard', + details: defaultVoteDetails, +} + export const isVoteFeatureSupported = (api: ApiPromise) => !!api.query.referenda?.referendumInfoFor && !!api.tx.convictionVoting?.vote diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx index 267d843e..25404552 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx @@ -1,7 +1,7 @@ import { Button } from '@components/ui/button' import { BaseToken } from '@domains/chains' import { useSelectedMultisig } from '@domains/multisig' -import { VoteDetails, isVoteDetailsComplete } from '@domains/referenda' +import { VoteDetailsState, isVoteDetailsComplete } from '@domains/referenda' import VoteOptions from './VoteOptions' import VoteStandard from './mode/VoteStandard' import { ProposalsDropdown } from './ProposalsDropdown' @@ -12,8 +12,8 @@ import { Vote } from '@talismn/icons' type Props = { token?: BaseToken - voteDetails: VoteDetails - onChange: (v: VoteDetails) => void + voteDetails: VoteDetailsState + onChange: (v: VoteDetailsState) => void onNext: () => void } @@ -22,8 +22,8 @@ const VotingForm: React.FC = ({ onChange, onNext, token, voteDetails }) = const { hasDelayedPermission, hasNonDelayedPermission } = hasPermission(multisig, 'governance') - const handleDetailsChange = (details: VoteDetails['details']) => { - onChange({ referendumId: voteDetails.referendumId, details }) + const handleDetailsChange = (details: VoteDetailsState['details']) => { + onChange({ ...voteDetails, details }) } return ( diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx index 6bd511d6..9656dc92 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx @@ -2,8 +2,8 @@ import { useMemo, useState } from 'react' import { SplitAbstainVoteParams, StandardVoteParams, - VoteDetails, - defaultVoteDetails, + VoteDetailsState, + defaultVote, isVoteDetailsComplete, isVoteFeatureSupported, } from '@domains/referenda' @@ -20,9 +20,7 @@ const VoteAction: React.FC = () => { const apiLoadable = useRecoilValueLoadable(pjsApiSelector(multisig.chain.genesisHash)) const tokens = useRecoilValueLoadable(selectedMultisigChainTokensState) const [reviewing, setReviewing] = useState(false) - const [voteDetails, setVoteDetails] = useState({ - details: { Standard: defaultVoteDetails.Standard }, - }) + const [voteDetails, setVoteDetails] = useState(defaultVote) const { toast } = useToast() // instead of allowing the user to select any token later on, we just use the first native token of the chain @@ -42,13 +40,19 @@ const VoteAction: React.FC = () => { ) return try { + const selectedConviction = { + ...defaultVote.details, + [voteDetails.convictionVote]: voteDetails.details[voteDetails.convictionVote], + } + const voteExtrinsic = apiLoadable.contents.tx?.convictionVoting.vote( voteDetails.referendumId, - voteDetails.details as + selectedConviction as | { Standard: StandardVoteParams } | { Split: SplitVoteParams } | { SplitAbstain: SplitAbstainVoteParams } ) + return voteExtrinsic } catch (e) { console.error(e) From c7d7e65f7b6208fb3118144f952471b8a4aab0f1 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Fri, 10 May 2024 15:38:04 +0700 Subject: [PATCH 02/29] refactor: simplified Standard Vote options state updates, so it does not intefere with other voting option states --- .../Vote/ConvictionsDropdown.tsx | 16 ++++++++-- .../NewTransaction/Vote/mode/VoteStandard.tsx | 29 ++++++------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx index 9218394c..d858691f 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx @@ -1,9 +1,10 @@ import { css } from '@emotion/css' import { Select } from '@talismn/ui' +import { VoteDetailsState } from '@domains/referenda' type Props = { conviction: number - onChange: (conviction: number) => void + setVoteDetails: React.Dispatch> } const CONVICTIONS = [1, 2, 4, 8, 16, 32].map((lock, index): [value: number, duration: number] => [index + 1, lock]) @@ -20,8 +21,17 @@ export function createConvictionsOpts(): { headlineText: string; value: number } } // ref: https://github.com/polkadot-js/apps/blob/master/packages/react-components/src/ConvictionDropdown.tsx -const ConvictionsDropdown: React.FC = ({ conviction, onChange }) => { +const ConvictionsDropdown: React.FC = ({ conviction, setVoteDetails }) => { const options = createConvictionsOpts() + + const handleChange = (value: number) => { + setVoteDetails(prev => { + const updatedVal = { ...prev } + updatedVal.details.Standard!.vote.conviction = value + return updatedVal + }) + } + return ( handleAmountChange(amount, direction)} /> ))} From 79cfcb337d50c0073e3ed4c8337de4fa5cc48e24 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Mon, 20 May 2024 11:29:19 +0700 Subject: [PATCH 18/29] feat: react-query initial setup --- apps/multisig/package.json | 3 + apps/multisig/src/App.tsx | 85 +++++++++++---------- yarn.lock | 152 ++++++++++++++++++++++++++++++++++--- 3 files changed, 191 insertions(+), 49 deletions(-) diff --git a/apps/multisig/package.json b/apps/multisig/package.json index 1d4791cf..1228d6a7 100644 --- a/apps/multisig/package.json +++ b/apps/multisig/package.json @@ -64,6 +64,8 @@ "@talismn/siws": "0.0.8", "@talismn/ui": "workspace:^", "@talismn/util": "^0.2.0", + "@tanstack/react-query": "^5.37.1", + "@tanstack/react-query-devtools": "^5.37.1", "@tanstack/react-table": "^8.16.0", "@uiw/codemirror-themes": "^4.21.13", "@uiw/react-codemirror": "^4.21.13", @@ -146,6 +148,7 @@ "@storybook/react": "^6.5.16", "@storybook/testing-library": "^0.0.13", "@talismn/development": "workspace:^", + "@tanstack/eslint-plugin-query": "^5.35.6", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^14.4.3", diff --git a/apps/multisig/src/App.tsx b/apps/multisig/src/App.tsx index 229aae71..ee0999b1 100644 --- a/apps/multisig/src/App.tsx +++ b/apps/multisig/src/App.tsx @@ -32,43 +32,52 @@ import { SkeletonLayout } from './layouts/SkeletonLayout' import { Helmet } from 'react-helmet' import { CONFIG } from '@lib/config' -const App: React.FC = () => ( - - - chain.genesisHash)} - coingeckoApiUrl="https://coingecko.talismn.workers.dev" - > - - - }> - - - {CONFIG.IS_POLKADOT_MULTISIG ? 'Polkadot Multisig by Signet' : 'Signet'} - - - {/* */} - - - - - - - - - - - {t => } - - - - - - - - - -) +import { useQuery, useMutation, useQueryClient, QueryClient, QueryClientProvider } from '@tanstack/react-query' +import { ReactQueryDevtools } from '@tanstack/react-query-devtools' + +const App: React.FC = () => { + const queryClient = new QueryClient() + return ( + + + chain.genesisHash)} + coingeckoApiUrl="https://coingecko.talismn.workers.dev" + > + + + }> + + + {CONFIG.IS_POLKADOT_MULTISIG ? 'Polkadot Multisig by Signet' : 'Signet'} + + + {/* */} + + + + + + + + + + + + + + {t => } + + + + + + + + + + ) +} export default App diff --git a/yarn.lock b/yarn.lock index e366c2b7..433fb67e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2928,7 +2928,7 @@ __metadata: languageName: node linkType: hard -"@eslint-community/eslint-utils@npm:^4.2.0": +"@eslint-community/eslint-utils@npm:^4.2.0, @eslint-community/eslint-utils@npm:^4.4.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" dependencies: @@ -10487,6 +10487,9 @@ __metadata: "@talismn/siws": 0.0.8 "@talismn/ui": "workspace:^" "@talismn/util": ^0.2.0 + "@tanstack/eslint-plugin-query": ^5.35.6 + "@tanstack/react-query": ^5.37.1 + "@tanstack/react-query-devtools": ^5.37.1 "@tanstack/react-table": ^8.16.0 "@testing-library/jest-dom": ^5.16.5 "@testing-library/react": ^13.4.0 @@ -10759,6 +10762,54 @@ __metadata: languageName: unknown linkType: soft +"@tanstack/eslint-plugin-query@npm:^5.35.6": + version: 5.35.6 + resolution: "@tanstack/eslint-plugin-query@npm:5.35.6" + dependencies: + "@typescript-eslint/utils": ^6.20.0 + peerDependencies: + eslint: ^8.0.0 + checksum: b95ed8541be636e5af175669a658da6cbb6eb849ef9f980152e7e4f684906ca266076ea18036d6dabaccd468b5a8219eb25752512d77e82d99077908772eaac8 + languageName: node + linkType: hard + +"@tanstack/query-core@npm:5.36.1": + version: 5.36.1 + resolution: "@tanstack/query-core@npm:5.36.1" + checksum: 9ac291eff02bcfd20c8460ce04683b2551d6b51635120eb9efb1be37c6839e8428ddf85ef94bf1b71ed162b5e5cd5dfef64e14f089058d725f7cee4d8ee07d0a + languageName: node + linkType: hard + +"@tanstack/query-devtools@npm:5.37.1": + version: 5.37.1 + resolution: "@tanstack/query-devtools@npm:5.37.1" + checksum: 73ef22b9a8a747fe8187c79e6673ff55f7feba85d57f95fd5bdb1c93f57ba57a19cc4f3f81cfe81adb18b73753e4e9046d3684fbc5bdd757d869ac274cf6f950 + languageName: node + linkType: hard + +"@tanstack/react-query-devtools@npm:^5.37.1": + version: 5.37.1 + resolution: "@tanstack/react-query-devtools@npm:5.37.1" + dependencies: + "@tanstack/query-devtools": 5.37.1 + peerDependencies: + "@tanstack/react-query": ^5.37.1 + react: ^18.0.0 + checksum: b73191d6e582f219522a7b9bd855ef21d9af37bab5ece7592fc98f0768f65fcf0e4116ce18f8baab2fd7c779ddf9277d09d221c1fa5d9aebad11e5300aa917c0 + languageName: node + linkType: hard + +"@tanstack/react-query@npm:^5.37.1": + version: 5.37.1 + resolution: "@tanstack/react-query@npm:5.37.1" + dependencies: + "@tanstack/query-core": 5.36.1 + peerDependencies: + react: ^18.0.0 + checksum: 4bac8aeed5ab6718ba3eb527542784c9475e3eda5f2602eea1479f672b5dfcfb48289b4a26ccf5ef3cba793e4b5cc00070b33e85417dda6ecbe11a09d85ad1c5 + languageName: node + linkType: hard + "@tanstack/react-table@npm:^8.16.0": version: 8.16.0 resolution: "@tanstack/react-table@npm:8.16.0" @@ -11283,7 +11334,7 @@ __metadata: languageName: node linkType: hard -"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.3, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": +"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.12, @types/json-schema@npm:^7.0.3, @types/json-schema@npm:^7.0.4, @types/json-schema@npm:^7.0.5, @types/json-schema@npm:^7.0.8, @types/json-schema@npm:^7.0.9": version: 7.0.15 resolution: "@types/json-schema@npm:7.0.15" checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98 @@ -11623,6 +11674,13 @@ __metadata: languageName: node linkType: hard +"@types/semver@npm:^7.5.0": + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 + languageName: node + linkType: hard + "@types/send@npm:*": version: 0.17.4 resolution: "@types/send@npm:0.17.4" @@ -11900,6 +11958,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/scope-manager@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/scope-manager@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + checksum: 71028b757da9694528c4c3294a96cc80bc7d396e383a405eab3bc224cda7341b88e0fc292120b35d3f31f47beac69f7083196c70616434072fbcd3d3e62d3376 + languageName: node + linkType: hard + "@typescript-eslint/type-utils@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/type-utils@npm:5.62.0" @@ -11924,6 +11992,13 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/types@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/types@npm:6.21.0" + checksum: 9501b47d7403417af95fc1fb72b2038c5ac46feac0e1598a46bcb43e56a606c387e9dcd8a2a0abe174c91b509f2d2a8078b093786219eb9a01ab2fbf9ee7b684 + languageName: node + linkType: hard + "@typescript-eslint/typescript-estree@npm:1.13.0": version: 1.13.0 resolution: "@typescript-eslint/typescript-estree@npm:1.13.0" @@ -11952,6 +12027,25 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/typescript-estree@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/typescript-estree@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/visitor-keys": 6.21.0 + debug: ^4.3.4 + globby: ^11.1.0 + is-glob: ^4.0.3 + minimatch: 9.0.3 + semver: ^7.5.4 + ts-api-utils: ^1.0.1 + peerDependenciesMeta: + typescript: + optional: true + checksum: dec02dc107c4a541e14fb0c96148f3764b92117c3b635db3a577b5a56fc48df7a556fa853fb82b07c0663b4bf2c484c9f245c28ba3e17e5cb0918ea4cab2ea21 + languageName: node + linkType: hard + "@typescript-eslint/utils@npm:5.62.0, @typescript-eslint/utils@npm:^5.45.0, @typescript-eslint/utils@npm:^5.58.0": version: 5.62.0 resolution: "@typescript-eslint/utils@npm:5.62.0" @@ -11970,6 +12064,23 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/utils@npm:^6.20.0": + version: 6.21.0 + resolution: "@typescript-eslint/utils@npm:6.21.0" + dependencies: + "@eslint-community/eslint-utils": ^4.4.0 + "@types/json-schema": ^7.0.12 + "@types/semver": ^7.5.0 + "@typescript-eslint/scope-manager": 6.21.0 + "@typescript-eslint/types": 6.21.0 + "@typescript-eslint/typescript-estree": 6.21.0 + semver: ^7.5.4 + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + checksum: b129b3a4aebec8468259f4589985cb59ea808afbfdb9c54f02fad11e17d185e2bf72bb332f7c36ec3c09b31f18fc41368678b076323e6e019d06f74ee93f7bf2 + languageName: node + linkType: hard + "@typescript-eslint/visitor-keys@npm:5.62.0": version: 5.62.0 resolution: "@typescript-eslint/visitor-keys@npm:5.62.0" @@ -11980,6 +12091,16 @@ __metadata: languageName: node linkType: hard +"@typescript-eslint/visitor-keys@npm:6.21.0": + version: 6.21.0 + resolution: "@typescript-eslint/visitor-keys@npm:6.21.0" + dependencies: + "@typescript-eslint/types": 6.21.0 + eslint-visitor-keys: ^3.4.1 + checksum: 67c7e6003d5af042d8703d11538fca9d76899f0119130b373402819ae43f0bc90d18656aa7add25a24427ccf1a0efd0804157ba83b0d4e145f06107d7d1b7433 + languageName: node + linkType: hard + "@uiw/codemirror-extensions-basic-setup@npm:4.21.21": version: 4.21.21 resolution: "@uiw/codemirror-extensions-basic-setup@npm:4.21.21" @@ -24692,6 +24813,15 @@ __metadata: languageName: node linkType: hard +"minimatch@npm:9.0.3, minimatch@npm:^9.0.1": + version: 9.0.3 + resolution: "minimatch@npm:9.0.3" + dependencies: + brace-expansion: ^2.0.1 + checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 + languageName: node + linkType: hard + "minimatch@npm:^3.0.2, minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" @@ -24710,15 +24840,6 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^9.0.1": - version: 9.0.3 - resolution: "minimatch@npm:9.0.3" - dependencies: - brace-expansion: ^2.0.1 - checksum: 253487976bf485b612f16bf57463520a14f512662e592e95c571afdab1442a6a6864b6c88f248ce6fc4ff0b6de04ac7aa6c8bb51e868e99d1d65eb0658a708b5 - languageName: node - linkType: hard - "minimist-options@npm:4.1.0": version: 4.1.0 resolution: "minimist-options@npm:4.1.0" @@ -32152,6 +32273,15 @@ storybook-preset-craco@artisanofcode/storybook-preset-craco: languageName: node linkType: hard +"ts-api-utils@npm:^1.0.1": + version: 1.3.0 + resolution: "ts-api-utils@npm:1.3.0" + peerDependencies: + typescript: ">=4.2.0" + checksum: c746ddabfdffbf16cb0b0db32bb287236a19e583057f8649ee7c49995bb776e1d3ef384685181c11a1a480369e022ca97512cb08c517b2d2bd82c83754c97012 + languageName: node + linkType: hard + "ts-dedent@npm:^2.0.0, ts-dedent@npm:^2.2.0": version: 2.2.0 resolution: "ts-dedent@npm:2.2.0" From 07596eb8ff0b30a6214be8519467acb92e3c272a Mon Sep 17 00:00:00 2001 From: Will Urban Date: Mon, 20 May 2024 16:11:39 +0700 Subject: [PATCH 19/29] feat: useGetReferendums hook --- .../src/hooks/queries/useGetReferendums.ts | 27 +++++++++++++++++ .../NewTransaction/Vote/PendingVotes.tsx | 29 ++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 apps/multisig/src/hooks/queries/useGetReferendums.ts diff --git a/apps/multisig/src/hooks/queries/useGetReferendums.ts b/apps/multisig/src/hooks/queries/useGetReferendums.ts new file mode 100644 index 00000000..55645c23 --- /dev/null +++ b/apps/multisig/src/hooks/queries/useGetReferendums.ts @@ -0,0 +1,27 @@ +import { useQueries } from '@tanstack/react-query' + +const fetchReferendums = async ({ id }: { id: string }) => { + const data = await fetch(`https://rococo.subsquare.io/api/gov2/referendums/${id}`).then(res => res.json()) + return data +} + +interface UseGetReferendums { + ids: string[] +} + +export default function useGetReferendums({ ids }: UseGetReferendums) { + return useQueries({ + queries: ids.map(id => ({ + queryKey: ['post', id], + queryFn: () => fetchReferendums({ id }), + enabled: !!id, + })), + combine: results => { + return { + data: results.map(result => result.data), + pending: results.some(result => result.isPending), + isLoading: results.some(result => result.isLoading), + } + }, + }) +} diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx index ca4d0516..74fe36b0 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx @@ -2,6 +2,7 @@ import { useEffect, useState, useCallback, useMemo } from 'react' import { useReferenda } from '@domains/referenda' import { useConfirmedTransactions } from '@domains/tx-history' import { useRecoilValue } from 'recoil' +import useGetReferendums from '@hooks/queries/useGetReferendums' import { selectedTeamsState } from '@domains/offchain-data' import { Button } from '@talismn/ui' import PendingVotesTable from './PendingVotesTable' @@ -18,11 +19,20 @@ interface PendingVotesProps { } const PendingVotes: React.FC = ({ multisig, handleOnRemoveVote }) => { - const [latestTxs, setLatestTxs] = useState([]) + const [referendumTxs, setReferendumTxs] = useState([]) const selectedTeams = useRecoilValue(selectedTeamsState) const { transactions, loading: isTransactionsLoading } = useConfirmedTransactions(selectedTeams ?? []) const { referendums, isLoading: isReferendumsLoading } = useReferenda(multisig.chain) + const txReferendumIds = useMemo( + () => referendumTxs.map(tx => String(tx.decoded!.voteDetails!.referendumId)), + [referendumTxs] + ) + + const { data: referendumsData, isLoading: isReferendumsDataLoading } = useGetReferendums({ ids: txReferendumIds }) + + console.log({ referendumsData }) + const ongoingReferendumsIds = useMemo( () => referendums?.flatMap(referendum => (referendum.isOngoing ? [referendum.index] : [])), [referendums] @@ -52,14 +62,23 @@ const PendingVotes: React.FC = ({ multisig, handleOnRemoveVot useEffect(() => { if (transactions?.length) { - setLatestTxs(filterLatestTransactions(transactions)) + setReferendumTxs(filterLatestTransactions(transactions)) } }, [filterLatestTransactions, transactions]) + console.log({ referendumTxs }) + const columns: ColumnDef[] = [ { header: 'Proposal', accessorKey: 'description', + cell: ({ row: { original } }) => { + const referendum = referendumsData?.find( + referendum => referendum.referendumIndex === Number(original.decoded?.voteDetails?.referendumId) + ) + console.log({ referendum }) + return
{referendum.title || original.description}
+ }, }, { id: 'voteFor', @@ -113,8 +132,10 @@ const PendingVotes: React.FC = ({ multisig, handleOnRemoveVot

Pending votes

) From c2bdc10d66f4e1806692af0ba3366856a06e58e2 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Mon, 20 May 2024 16:12:19 +0700 Subject: [PATCH 20/29] feat: display title, memoise columns --- .../NewTransaction/Vote/PendingVotes.tsx | 109 +++++++++--------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx index 74fe36b0..bd9ccfdd 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx @@ -31,8 +31,6 @@ const PendingVotes: React.FC = ({ multisig, handleOnRemoveVot const { data: referendumsData, isLoading: isReferendumsDataLoading } = useGetReferendums({ ids: txReferendumIds }) - console.log({ referendumsData }) - const ongoingReferendumsIds = useMemo( () => referendums?.flatMap(referendum => (referendum.isOngoing ? [referendum.index] : [])), [referendums] @@ -66,66 +64,66 @@ const PendingVotes: React.FC = ({ multisig, handleOnRemoveVot } }, [filterLatestTransactions, transactions]) - console.log({ referendumTxs }) - - const columns: ColumnDef[] = [ - { - header: 'Proposal', - accessorKey: 'description', - cell: ({ row: { original } }) => { - const referendum = referendumsData?.find( - referendum => referendum.referendumIndex === Number(original.decoded?.voteDetails?.referendumId) - ) - console.log({ referendum }) - return
{referendum.title || original.description}
+ const columns: ColumnDef[] = useMemo( + () => [ + { + header: 'Proposal', + accessorKey: 'description', + cell: ({ row: { original } }) => { + const referendum = referendumsData?.find( + referendum => referendum?.referendumIndex === Number(original.decoded?.voteDetails?.referendumId) + ) + return
{referendum?.title || original.description}
+ }, }, - }, - { - id: 'voteFor', - cell: ({ row: { original } }) => { - return ( -
- -
- ) + { + id: 'voteFor', + cell: ({ row: { original } }) => { + return ( +
+ +
+ ) + }, }, - }, - { - id: 'amount', - cell: ({ row: { original } }) => { - const { convictionVote, details, token, method } = original.decoded?.voteDetails! - const { Standard, SplitAbstain } = details + { + id: 'amount', + cell: ({ row: { original } }) => { + const { convictionVote, details, token, method } = original.decoded?.voteDetails! + const { Standard, SplitAbstain } = details - if (!method) return null + if (!method) return null - const amount = - convictionVote === 'SplitAbstain' - ? Object.values(SplitAbstain!).reduce((acc, balance) => acc.add(balance), new BN(0)) - : new BN(0) + const amount = + convictionVote === 'SplitAbstain' + ? Object.values(SplitAbstain!).reduce((acc, balance) => acc.add(balance), new BN(0)) + : new BN(0) - return + return + }, }, - }, - { - id: 'conviction', - cell: ({ row: { original } }) => { - if (original.decoded?.voteDetails?.convictionVote !== 'Standard') return null - return
{original.decoded?.voteDetails?.details.Standard?.vote.conviction}x
+ { + id: 'conviction', + cell: ({ row: { original } }) => { + if (original.decoded?.voteDetails?.convictionVote !== 'Standard') return null + return
{original.decoded?.voteDetails?.details.Standard?.vote.conviction}x
+ }, }, - }, - { - id: 'actions', - cell: ({ row: { original } }) => { - return ( -
- -
- ) + { + id: 'actions', + cell: ({ row: { original } }) => { + return ( +
+ +
+ ) + }, }, - }, - ] + ], + [handleOnRemoveVote, referendumsData] + ) return (
@@ -134,7 +132,8 @@ const PendingVotes: React.FC = ({ multisig, handleOnRemoveVot columns={columns} data={referendumTxs} isLoading={ - (isTransactionsLoading || isReferendumsLoading || isReferendumsDataLoading) && referendumTxs.length === 0 + (isTransactionsLoading || isReferendumsLoading || (isReferendumsDataLoading && !referendumsData.length)) && + referendumTxs.length === 0 } />
From dafa6f15fa571fedbc89a3be8733e2ef0cbb4c59 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Mon, 20 May 2024 17:20:17 +0700 Subject: [PATCH 21/29] feat: dynamically fetch and cache by chain --- .../src/hooks/queries/useGetReferendums.ts | 32 +++++++++++++++---- .../NewTransaction/Vote/PendingVotes.tsx | 7 ++-- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/apps/multisig/src/hooks/queries/useGetReferendums.ts b/apps/multisig/src/hooks/queries/useGetReferendums.ts index 55645c23..9965178d 100644 --- a/apps/multisig/src/hooks/queries/useGetReferendums.ts +++ b/apps/multisig/src/hooks/queries/useGetReferendums.ts @@ -1,20 +1,40 @@ import { useQueries } from '@tanstack/react-query' +import { SupportedChainIds } from '@domains/chains/generated-chains' -const fetchReferendums = async ({ id }: { id: string }) => { - const data = await fetch(`https://rococo.subsquare.io/api/gov2/referendums/${id}`).then(res => res.json()) +// Use PartialRecord to create the supportedChains object +const supportedChains: Partial> = { + 'polkadot': 'polkadot', + 'kusama': 'kusama', + 'acala': 'acala', + 'bifrost-polkadot': 'bifrost', + 'bifrost-kusama': 'bifrost-kusama', + 'hydradx': 'hydradx', + 'phala': 'phala', + 'khala': 'khala', + 'karura': 'karura', + 'kintsugi': 'kintsugi', + // testnets + 'rococo-testnet': 'rococo', +} + +const fetchReferendums = async ({ chain, id }: { chain: string | undefined; id: string }) => { + const data = await fetch(`https://${chain}.subsquare.io/api/gov2/referendums/${id}`).then(res => res.json()) return data } interface UseGetReferendums { ids: string[] + chainId: SupportedChainIds } -export default function useGetReferendums({ ids }: UseGetReferendums) { +export default function useGetReferendums({ ids, chainId }: UseGetReferendums) { + const chain = supportedChains[chainId] + return useQueries({ queries: ids.map(id => ({ - queryKey: ['post', id], - queryFn: () => fetchReferendums({ id }), - enabled: !!id, + queryKey: [chain, id], + queryFn: () => fetchReferendums({ chain, id }), + enabled: !!id && !!chain, })), combine: results => { return { diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx index bd9ccfdd..59457335 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx @@ -12,6 +12,7 @@ import { Multisig } from '@domains/multisig' import { Transaction } from '@domains/multisig' import { ColumnDef } from '@tanstack/react-table' import BN from 'bn.js' +import { SupportedChainIds } from '@domains/chains/generated-chains' interface PendingVotesProps { multisig: Multisig @@ -28,8 +29,10 @@ const PendingVotes: React.FC = ({ multisig, handleOnRemoveVot () => referendumTxs.map(tx => String(tx.decoded!.voteDetails!.referendumId)), [referendumTxs] ) - - const { data: referendumsData, isLoading: isReferendumsDataLoading } = useGetReferendums({ ids: txReferendumIds }) + const { data: referendumsData, isLoading: isReferendumsDataLoading } = useGetReferendums({ + chainId: multisig.chain.squidIds.chainData as SupportedChainIds, + ids: txReferendumIds, + }) const ongoingReferendumsIds = useMemo( () => referendums?.flatMap(referendum => (referendum.isOngoing ? [referendum.index] : [])), From daa26f960e0d5bb23eeab34f909dee3921257019 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Mon, 20 May 2024 17:27:52 +0700 Subject: [PATCH 22/29] chore: added type to fetchReferendum --- apps/multisig/src/hooks/queries/useGetReferendums.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/multisig/src/hooks/queries/useGetReferendums.ts b/apps/multisig/src/hooks/queries/useGetReferendums.ts index 9965178d..0170ba25 100644 --- a/apps/multisig/src/hooks/queries/useGetReferendums.ts +++ b/apps/multisig/src/hooks/queries/useGetReferendums.ts @@ -16,8 +16,13 @@ const supportedChains: Partial> = { // testnets 'rococo-testnet': 'rococo', } +// This only a partial Referendum interface +interface Referendum { + title: string + referendumIndex: number +} -const fetchReferendums = async ({ chain, id }: { chain: string | undefined; id: string }) => { +const fetchReferendums = async ({ chain, id }: { chain: string | undefined; id: string }): Promise => { const data = await fetch(`https://${chain}.subsquare.io/api/gov2/referendums/${id}`).then(res => res.json()) return data } From adbcef6d2266a095276b30b682aeb04f22db0bb2 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Mon, 20 May 2024 17:40:41 +0700 Subject: [PATCH 23/29] refactor: added isChainSupported to cache query key --- apps/multisig/src/hooks/queries/useGetReferendums.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/multisig/src/hooks/queries/useGetReferendums.ts b/apps/multisig/src/hooks/queries/useGetReferendums.ts index 0170ba25..9edf04ab 100644 --- a/apps/multisig/src/hooks/queries/useGetReferendums.ts +++ b/apps/multisig/src/hooks/queries/useGetReferendums.ts @@ -37,7 +37,7 @@ export default function useGetReferendums({ ids, chainId }: UseGetReferendums) { return useQueries({ queries: ids.map(id => ({ - queryKey: [chain, id], + queryKey: [chainId, { isChainSupported: !!chain }, id], queryFn: () => fetchReferendums({ chain, id }), enabled: !!id && !!chain, })), From 51f50b2b3c8d2770cba500e0a7c3aa5d3a457bf3 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Tue, 21 May 2024 09:21:37 +0700 Subject: [PATCH 24/29] feat: display Referendum name on ProposalsDropdown --- .../src/hooks/queries/useGetReferendums.ts | 1 - .../NewTransaction/Vote/ProposalsDropdown.tsx | 34 ++++++++++++++----- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/apps/multisig/src/hooks/queries/useGetReferendums.ts b/apps/multisig/src/hooks/queries/useGetReferendums.ts index 9edf04ab..1413b3c2 100644 --- a/apps/multisig/src/hooks/queries/useGetReferendums.ts +++ b/apps/multisig/src/hooks/queries/useGetReferendums.ts @@ -1,7 +1,6 @@ import { useQueries } from '@tanstack/react-query' import { SupportedChainIds } from '@domains/chains/generated-chains' -// Use PartialRecord to create the supportedChains object const supportedChains: Partial> = { 'polkadot': 'polkadot', 'kusama': 'kusama', diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/ProposalsDropdown.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/ProposalsDropdown.tsx index f71af522..bde004c5 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/ProposalsDropdown.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/ProposalsDropdown.tsx @@ -2,6 +2,9 @@ import { Chain } from '@domains/chains' import { useReferenda } from '@domains/referenda' import { Select } from '@talismn/ui' import { css } from '@emotion/css' +import useGetReferendums from '@hooks/queries/useGetReferendums' +import { SupportedChainIds } from '@domains/chains/generated-chains' +import clsx from 'clsx' type Props = { chain: Chain @@ -13,20 +16,35 @@ export const ProposalsDropdown: React.FC = ({ chain, referendumId, onChan const { referendums } = useReferenda(chain) const ongoingReferendums = referendums?.filter(referendum => referendum.isOngoing) + const { data: referendumsData, isLoading: isReferendumsDataLoading } = useGetReferendums({ + chainId: chain.squidIds.chainData as SupportedChainIds, + ids: ongoingReferendums?.map(referendum => String(referendum.index)) ?? [], + }) + return ( ) } From ec0414eae1b1e7e1d35721cc395fad23dc47b001 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Wed, 22 May 2024 11:26:50 +0700 Subject: [PATCH 25/29] refactor: add referendumId to titles --- .../layouts/NewTransaction/Vote/PendingVotes.tsx | 8 ++++---- .../NewTransaction/Vote/ProposalsDropdown.tsx | 13 ++++--------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx index 59457335..1d264647 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx @@ -73,10 +73,10 @@ const PendingVotes: React.FC = ({ multisig, handleOnRemoveVot header: 'Proposal', accessorKey: 'description', cell: ({ row: { original } }) => { - const referendum = referendumsData?.find( - referendum => referendum?.referendumIndex === Number(original.decoded?.voteDetails?.referendumId) - ) - return
{referendum?.title || original.description}
+ const referendumId = original.decoded?.voteDetails?.referendumId + const { title } = referendumsData?.find(ref => ref?.referendumIndex === referendumId) || {} + const headlineText = title ? `Proposal #${referendumId} - ${title}` : `Proposal #${referendumId}` + return
{headlineText}
}, }, { diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/ProposalsDropdown.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/ProposalsDropdown.tsx index bde004c5..d7d9217c 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/ProposalsDropdown.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/ProposalsDropdown.tsx @@ -16,7 +16,7 @@ export const ProposalsDropdown: React.FC = ({ chain, referendumId, onChan const { referendums } = useReferenda(chain) const ongoingReferendums = referendums?.filter(referendum => referendum.isOngoing) - const { data: referendumsData, isLoading: isReferendumsDataLoading } = useGetReferendums({ + const { data: referendumsData } = useGetReferendums({ chainId: chain.squidIds.chainData as SupportedChainIds, ids: ongoingReferendums?.map(referendum => String(referendum.index)) ?? [], }) @@ -36,14 +36,9 @@ export const ProposalsDropdown: React.FC = ({ chain, referendumId, onChan onChange={onChange} > {ongoingReferendums?.map(referendum => { - const referendumData = referendumsData?.find(ref => ref?.referendumIndex === referendum.index) - return ( - - ) + const { title } = referendumsData?.find(ref => ref?.referendumIndex === referendum.index) || {} + const headlineText = title ? `Proposal #${referendum.index} - ${title}` : `Proposal #${referendum.index}` + return })} ) From d3febc5b3cba25e0d27edb16e1cb95f6bcbc5372 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Wed, 22 May 2024 12:05:53 +0700 Subject: [PATCH 26/29] refactor: memoized renderExpandedDetails --- .../Transactions/VoteTransactionDetails.tsx | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/apps/multisig/src/layouts/Overview/Transactions/VoteTransactionDetails.tsx b/apps/multisig/src/layouts/Overview/Transactions/VoteTransactionDetails.tsx index 5618886d..cc781082 100644 --- a/apps/multisig/src/layouts/Overview/Transactions/VoteTransactionDetails.tsx +++ b/apps/multisig/src/layouts/Overview/Transactions/VoteTransactionDetails.tsx @@ -1,3 +1,4 @@ +import { useMemo } from 'react' import { Transaction, TransactionType } from '@domains/multisig' import { css } from '@emotion/css' import { ExternalLink } from '@talismn/icons' @@ -49,11 +50,9 @@ export const VotePill: React.FC<{ voteDetails: VoteDetails }> = ({ voteDetails } export const VoteTransactionHeaderContent: React.FC = ({ t }) => { if (t.decoded?.type !== TransactionType.Vote || !t.decoded.voteDetails) return null - const { method, convictionVote, details, token } = t.decoded.voteDetails + const { convictionVote, details, token } = t.decoded.voteDetails const { Standard, SplitAbstain } = details - if (!method) return null - const amount = convictionVote === 'SplitAbstain' ? Object.values(SplitAbstain!).reduce((acc, balance) => acc.add(balance), new BN(0)) @@ -75,16 +74,15 @@ export const VoteTransactionHeaderContent: React.FC = ({ t }) => { } export const VoteExpandedDetails: React.FC = ({ t }) => { - if (t.decoded?.type !== TransactionType.Vote || !t.decoded.voteDetails) return null - - const { referendumId, method, details, token } = t.decoded.voteDetails - const { Standard, SplitAbstain } = details + const renderExpandedDetails = useMemo(() => { + if (t.decoded?.type !== TransactionType.Vote || !t.decoded.voteDetails) return null - const convictionsOptions = createConvictionsOpts() + const convictionsOptions = createConvictionsOpts() + const { + details: { Standard, SplitAbstain }, + token, + } = t?.decoded?.voteDetails - if (!method) return null - - const renderExpandedDetails = () => { if (Standard) { return ( <> @@ -123,8 +121,11 @@ export const VoteExpandedDetails: React.FC = ({ t }) => { ) } - } + }, [t.decoded?.type, t?.decoded?.voteDetails]) + + if (t.decoded?.type !== TransactionType.Vote || !t.decoded.voteDetails) return null + const { referendumId } = t?.decoded?.voteDetails const name = `Referendum #${referendumId}` return ( @@ -148,7 +149,7 @@ export const VoteExpandedDetails: React.FC = ({ t }) => { )} - {renderExpandedDetails()} + {renderExpandedDetails} ) From 2b80af6a680634e6257849dcb075ee0a8ca1398d Mon Sep 17 00:00:00 2001 From: Will Urban Date: Wed, 22 May 2024 12:23:22 +0700 Subject: [PATCH 27/29] refactor: added try catch block to useReferenda --- apps/multisig/src/domains/referenda/index.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/multisig/src/domains/referenda/index.ts b/apps/multisig/src/domains/referenda/index.ts index a4b7f80d..74f5faa4 100644 --- a/apps/multisig/src/domains/referenda/index.ts +++ b/apps/multisig/src/domains/referenda/index.ts @@ -89,7 +89,9 @@ export const useReferenda = (chain: Chain) => { // treat it as 0 referendum created if required pallets are not supported setReferendums([]) setIsLoading(false) - } else { + return + } + try { const referendumCount = await apiLoadable.contents.query.referenda.referendumCount() const ids = Array.from(Array(referendumCount.toNumber()).keys()) const rawReferendums = await apiLoadable.contents.query.referenda.referendumInfoFor.multi(ids) @@ -100,6 +102,9 @@ export const useReferenda = (chain: Chain) => { isOngoing: raw.value.isOngoing, })) ) + } catch (error) { + console.error(`Error while fetching referenda: ${error}`) + } finally { setIsLoading(false) } }, [apiLoadable, chain.chainName, isPalletSupported]) From 6fefbedd030edcdfcecb2e1016d73368b6c16244 Mon Sep 17 00:00:00 2001 From: Will Urban Date: Wed, 22 May 2024 13:35:58 +0700 Subject: [PATCH 28/29] refactor: added VoteDetailsForm type for client side vote tx building --- apps/multisig/src/domains/referenda/index.ts | 12 ++++++++++-- .../NewTransaction/Vote/ConvictionsDropdown.tsx | 4 ++-- .../src/layouts/NewTransaction/Vote/VoteOptions.tsx | 6 +++--- .../src/layouts/NewTransaction/Vote/VotingForm.tsx | 6 +++--- .../src/layouts/NewTransaction/Vote/index.tsx | 4 ++-- .../NewTransaction/Vote/mode/VoteSplitAbstain.tsx | 4 ++-- .../NewTransaction/Vote/mode/VoteStandard.tsx | 4 ++-- 7 files changed, 24 insertions(+), 16 deletions(-) diff --git a/apps/multisig/src/domains/referenda/index.ts b/apps/multisig/src/domains/referenda/index.ts index 74f5faa4..aab96d05 100644 --- a/apps/multisig/src/domains/referenda/index.ts +++ b/apps/multisig/src/domains/referenda/index.ts @@ -36,6 +36,14 @@ export type VoteDetails = { } } +export type VoteDetailsForm = Omit & { + details: { + Standard: StandardVoteParams + Split: SplitVoteParams + SplitAbstain: SplitAbstainVoteParams + } +} + type ReferendumBasicInfo = { index: number isOngoing: boolean @@ -61,7 +69,7 @@ export const defaultVoteDetails: Required = { }, } -export const defaultVote: VoteDetails = { +export const defaultVote: VoteDetailsForm = { convictionVote: 'Standard', method: 'vote', details: defaultVoteDetails, @@ -121,7 +129,7 @@ export const useReferenda = (chain: Chain) => { return { referendums, isPalletSupported, isLoading } } -export const isVoteDetailsComplete = (voteDetails: VoteDetails) => { +export const isVoteDetailsComplete = (voteDetails: VoteDetailsForm) => { if (voteDetails.referendumId === undefined) return false if (voteDetails.convictionVote === 'Standard') { diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx index 1e0140c3..ed2e8b61 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx @@ -1,10 +1,10 @@ import { css } from '@emotion/css' import { Select } from '@talismn/ui' -import { VoteDetails } from '@domains/referenda' +import { VoteDetailsForm } from '@domains/referenda' type Props = { conviction: number - setVoteDetails: React.Dispatch> + setVoteDetails: React.Dispatch> } const CONVICTIONS = [1, 2, 4, 8, 16, 32].map((lock, index): [value: number, duration: number] => [index + 1, lock]) diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/VoteOptions.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/VoteOptions.tsx index d58b6f48..4998b4d0 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/VoteOptions.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/VoteOptions.tsx @@ -1,10 +1,10 @@ import { css } from '@emotion/css' import { Button } from '@talismn/ui' -import { VoteDetails } from '@domains/referenda' +import { VoteDetailsForm } from '@domains/referenda' type Props = { - voteDetails: VoteDetails - setVoteDetails: React.Dispatch> + voteDetails: VoteDetailsForm + setVoteDetails: React.Dispatch> } const VoteOptions: React.FC = ({ voteDetails, setVoteDetails }) => { diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx index cdb30f64..96394b30 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx @@ -2,7 +2,7 @@ import React from 'react' import { Button } from '@components/ui/button' import { BaseToken } from '@domains/chains' import { useSelectedMultisig } from '@domains/multisig' -import { VoteDetails, isVoteDetailsComplete } from '@domains/referenda' +import { VoteDetailsForm, isVoteDetailsComplete } from '@domains/referenda' import VoteOptions from './VoteOptions' import VoteSplitAbstain from './mode/VoteSplitAbstain' import VoteStandard from './mode/VoteStandard' @@ -14,8 +14,8 @@ import { Vote } from '@talismn/icons' type Props = { token?: BaseToken - voteDetails: VoteDetails - setVoteDetails: React.Dispatch> + voteDetails: VoteDetailsForm + setVoteDetails: React.Dispatch> onNext: () => void } diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx index 2b691566..070ff31d 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from 'react' import { SplitAbstainVoteParams, StandardVoteParams, - VoteDetails, + VoteDetailsForm, defaultVote, isVoteDetailsComplete, isVoteFeatureSupported, @@ -22,7 +22,7 @@ const VoteAction: React.FC = () => { const tokens = useRecoilValueLoadable(selectedMultisigChainTokensState) const [reviewing, setReviewing] = useState(false) const [removeVoteId, setRemoveVoteId] = useState(null) - const [voteDetails, setVoteDetails] = useState(defaultVote) + const [voteDetails, setVoteDetails] = useState(defaultVote) const { toast } = useToast() // instead of allowing the user to select any token later on, we just use the first native token of the chain diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteSplitAbstain.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteSplitAbstain.tsx index 1c9c37ec..f56c6d46 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteSplitAbstain.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteSplitAbstain.tsx @@ -1,12 +1,12 @@ import { BaseToken } from '@domains/chains' -import { VoteDetails } from '@domains/referenda' +import { VoteDetailsForm } from '@domains/referenda' import { AmountFlexibleInput } from '@components/AmountFlexibleInput' import { parseUnits } from '@util/numbers' import BN from 'bn.js' interface VoteSplitAbstainProps { token?: BaseToken - setVoteDetails: React.Dispatch> + setVoteDetails: React.Dispatch> } enum VoteDirection { diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteStandard.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteStandard.tsx index 28252ed2..92bf028d 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteStandard.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteStandard.tsx @@ -1,14 +1,14 @@ import React from 'react' import { AmountFlexibleInput } from '@components/AmountFlexibleInput' import { BaseToken } from '@domains/chains' -import { StandardVoteParams, VoteDetails } from '@domains/referenda' +import { StandardVoteParams, VoteDetailsForm } from '@domains/referenda' import ConvictionsDropdown from '../ConvictionsDropdown' import { parseUnits } from '@util/numbers' import BN from 'bn.js' type Props = { token?: BaseToken - setVoteDetails: React.Dispatch> + setVoteDetails: React.Dispatch> params: StandardVoteParams } From 0e980e80839c441372a9259db379e35764b49c7b Mon Sep 17 00:00:00 2001 From: Will Urban Date: Wed, 22 May 2024 13:36:48 +0700 Subject: [PATCH 29/29] refactor: removed unnecessary non-null asserts and optional chaining --- apps/multisig/src/domains/referenda/index.ts | 4 ++-- .../NewTransaction/Vote/ConvictionsDropdown.tsx | 2 +- .../src/layouts/NewTransaction/Vote/PendingVotes.tsx | 4 ++-- .../src/layouts/NewTransaction/Vote/VoteOptions.tsx | 12 ++++++------ .../src/layouts/NewTransaction/Vote/VotingForm.tsx | 2 +- .../src/layouts/NewTransaction/Vote/index.tsx | 4 ++-- .../NewTransaction/Vote/mode/VoteSplitAbstain.tsx | 4 ++-- .../NewTransaction/Vote/mode/VoteStandard.tsx | 2 +- .../Overview/Transactions/VoteTransactionDetails.tsx | 2 +- 9 files changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/multisig/src/domains/referenda/index.ts b/apps/multisig/src/domains/referenda/index.ts index aab96d05..876915ed 100644 --- a/apps/multisig/src/domains/referenda/index.ts +++ b/apps/multisig/src/domains/referenda/index.ts @@ -133,10 +133,10 @@ export const isVoteDetailsComplete = (voteDetails: VoteDetailsForm) => { if (voteDetails.referendumId === undefined) return false if (voteDetails.convictionVote === 'Standard') { - const { balance } = voteDetails.details.Standard! + const { balance } = voteDetails.details.Standard return balance.gt(new BN(0)) } else if (voteDetails.convictionVote === 'SplitAbstain') { - const { aye, nay, abstain } = voteDetails.details.SplitAbstain! + const { aye, nay, abstain } = voteDetails.details.SplitAbstain return aye.gt(new BN(0)) || nay.gt(new BN(0)) || abstain.gt(new BN(0)) } return !!voteDetails.details.Split diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx index ed2e8b61..56173291 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/ConvictionsDropdown.tsx @@ -27,7 +27,7 @@ const ConvictionsDropdown: React.FC = ({ conviction, setVoteDetails }) => const handleChange = (value: number) => { setVoteDetails(prev => { const updatedVal = { ...prev } - updatedVal.details.Standard!.vote.conviction = value + updatedVal.details.Standard.vote.conviction = value return updatedVal }) } diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx index ca4d0516..6ef126a6 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/PendingVotes.tsx @@ -80,8 +80,8 @@ const PendingVotes: React.FC = ({ multisig, handleOnRemoveVot if (!method) return null const amount = - convictionVote === 'SplitAbstain' - ? Object.values(SplitAbstain!).reduce((acc, balance) => acc.add(balance), new BN(0)) + convictionVote === 'SplitAbstain' && SplitAbstain + ? Object.values(SplitAbstain).reduce((acc, balance) => acc.add(balance), new BN(0)) : new BN(0) return diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/VoteOptions.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/VoteOptions.tsx index 4998b4d0..e0efd3a8 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/VoteOptions.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/VoteOptions.tsx @@ -26,12 +26,12 @@ const VoteOptions: React.FC = ({ voteDetails, setVoteDetails }) => { setVoteDetails(prev => { const updatedDetails = { ...prev } updatedDetails.convictionVote = 'Standard' - updatedDetails.details.Standard!.vote.aye = true + updatedDetails.details.Standard.vote.aye = true return updatedDetails }) }} variant={ - voteDetails.details.Standard?.vote.aye && voteDetails.convictionVote === 'Standard' ? undefined : 'secondary' + voteDetails.details.Standard.vote.aye && voteDetails.convictionVote === 'Standard' ? undefined : 'secondary' } > Aye @@ -41,18 +41,18 @@ const VoteOptions: React.FC = ({ voteDetails, setVoteDetails }) => { setVoteDetails(prev => { const updatedDetails = { ...prev } updatedDetails.convictionVote = 'Standard' - updatedDetails.details.Standard!.vote.aye = false + updatedDetails.details.Standard.vote.aye = false return updatedDetails }) }} css={({ color }) => ({ backgroundColor: - voteDetails.details.Standard?.vote.aye === false && voteDetails.convictionVote === 'Standard' + voteDetails.details.Standard.vote.aye === false && voteDetails.convictionVote === 'Standard' ? '#f46161' : undefined, })} variant={ - voteDetails.details.Standard?.vote.aye === false && voteDetails.convictionVote === 'Standard' + voteDetails.details.Standard.vote.aye === false && voteDetails.convictionVote === 'Standard' ? undefined : 'secondary' } @@ -64,7 +64,7 @@ const VoteOptions: React.FC = ({ voteDetails, setVoteDetails }) => { setVoteDetails(prev => { const updatedDetails = { ...prev } updatedDetails.convictionVote = 'SplitAbstain' - updatedDetails.details.Standard!.vote.aye = true + updatedDetails.details.Standard.vote.aye = true return updatedDetails }) }} diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx index 96394b30..97b88d9e 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/VotingForm.tsx @@ -35,7 +35,7 @@ const VotingForm: React.FC = ({ setVoteDetails, onNext, token, voteDetail /> {voteDetails.convictionVote === 'Standard' ? ( - + ) : ( // TODO: add UI for Split votes diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx index 070ff31d..c36d0bf9 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/index.tsx @@ -70,12 +70,12 @@ const VoteAction: React.FC = () => { if (removeVoteId) { return `Remove vote on Proposal #${removeVoteId}` } - let vote = voteDetails.details.Standard?.vote.aye ? 'Aye' : 'Nay' + let vote = voteDetails.details.Standard.vote.aye ? 'Aye' : 'Nay' if (voteDetails.convictionVote === 'SplitAbstain') { vote = 'Abstain' } return `Vote ${vote} on Proposal #${voteDetails.referendumId}` - }, [removeVoteId, voteDetails.convictionVote, voteDetails.details.Standard?.vote.aye, voteDetails.referendumId]) + }, [removeVoteId, voteDetails.convictionVote, voteDetails.details.Standard.vote.aye, voteDetails.referendumId]) return (
diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteSplitAbstain.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteSplitAbstain.tsx index f56c6d46..a2b58d36 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteSplitAbstain.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteSplitAbstain.tsx @@ -28,11 +28,11 @@ export default function VoteSplitAbstain({ token, setVoteDetails }: VoteSplitAbs } setVoteDetails(prev => { - const prevBal = prev.details.SplitAbstain![field] + const prevBal = prev.details.SplitAbstain[field] if (balance.eq(prevBal)) return prev const updatedVal = { ...prev } - updatedVal.details.SplitAbstain![field] = balance + updatedVal.details.SplitAbstain[field] = balance return updatedVal }) } diff --git a/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteStandard.tsx b/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteStandard.tsx index 92bf028d..4fa3fa8c 100644 --- a/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteStandard.tsx +++ b/apps/multisig/src/layouts/NewTransaction/Vote/mode/VoteStandard.tsx @@ -27,7 +27,7 @@ const VoteStandard = ({ params, setVoteDetails, token }: Props) => { setVoteDetails(prev => { const updatedVal = { ...prev } - updatedVal.details.Standard!.balance = balance + updatedVal.details.Standard.balance = balance return updatedVal }) } diff --git a/apps/multisig/src/layouts/Overview/Transactions/VoteTransactionDetails.tsx b/apps/multisig/src/layouts/Overview/Transactions/VoteTransactionDetails.tsx index cc781082..be82bb13 100644 --- a/apps/multisig/src/layouts/Overview/Transactions/VoteTransactionDetails.tsx +++ b/apps/multisig/src/layouts/Overview/Transactions/VoteTransactionDetails.tsx @@ -105,7 +105,7 @@ export const VoteExpandedDetails: React.FC = ({ t }) => { if (SplitAbstain) { return ( <> - {Object.entries(SplitAbstain!) + {Object.entries(SplitAbstain) .map(([key, balance]) => (

{key} vote value