From 8de25755bb0cb98f11c954d6a6f8c683b601d2c7 Mon Sep 17 00:00:00 2001 From: vetalcore Date: Mon, 4 Mar 2024 14:44:44 +0200 Subject: [PATCH 1/4] feat(extension): handle requests from non registered users --- .../ConfirmTransaction.tsx | 7 +- .../NonRegisteredUserModal.module.scss | 52 ++++++++ .../NonRegisteredUserModal.tsx | 50 ++++++++ .../VotingProceduresContainer.tsx | 111 +++++++++++------- .../VotingProceduresContainer.test.tsx | 97 ++++++++++++++- .../__tests__/utils.test.tsx | 58 ++++++++- .../components/confirm-transaction/hooks.ts | 2 +- .../components/confirm-transaction/utils.ts | 15 +++ .../src/lib/translations/en.json | 8 ++ 9 files changed, 349 insertions(+), 51 deletions(-) create mode 100644 apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/NonRegisteredUserModal/NonRegisteredUserModal.module.scss create mode 100644 apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/NonRegisteredUserModal/NonRegisteredUserModal.tsx diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmTransaction.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmTransaction.tsx index 333ea17d3e..a49bcd69a4 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmTransaction.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmTransaction.tsx @@ -20,6 +20,7 @@ import { UserPromptService } from '@lib/scripts/background/services'; import { DAPP_CHANNELS } from '@src/utils/constants'; import { of, take } from 'rxjs'; import { runtime } from 'webextension-polyfill'; +import { Skeleton } from 'antd'; export const ConfirmTransaction = (): React.ReactElement => { const { t } = useTranslation(); @@ -92,7 +93,11 @@ export const ConfirmTransaction = (): React.ReactElement => { pageClassname={styles.spaceBetween} title={!confirmTransactionError && txType && t(`core.${txType}.title`)} > - {req && txType && setConfirmTransactionError(true)} />} + {req && txType ? ( + setConfirmTransactionError(true)} /> + ) : ( + + )} {!confirmTransactionError && (
+ +
+ + + ); +}; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx index d85526fb16..87eaebc6d7 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx @@ -1,11 +1,13 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { VotingProcedures } from '@lace/core'; -import { drepIDasBech32FromHash, votingProceduresInspector } from './utils'; -import { useCexplorerBaseUrl } from './hooks'; +import { drepIDasBech32FromHash, hasValidDrepRegistration, votingProceduresInspector } from './utils'; +import { useCexplorerBaseUrl, useDisallowSignTx } from './hooks'; import { VoterTypeEnum, getVote, getVoterType } from '@src/utils/tx-inspection'; import { Wallet } from '@lace/cardano'; +import { NonRegisteredUserModal } from './NonRegisteredUserModal/NonRegisteredUserModal'; import { useViewsFlowContext } from '@providers'; +import { useWalletStore } from '@src/stores'; export const VotingProceduresContainer = (): React.ReactElement => { const { t } = useTranslation(); @@ -13,7 +15,11 @@ export const VotingProceduresContainer = (): React.ReactElement => { signTxRequest: { request }, dappInfo } = useViewsFlowContext(); + const { walletState } = useWalletStore(); const [votingProcedures, setVotingProcedures] = useState([]); + const [isNonRegisteredUserModalVisible, setIsNonRegisteredUserModalVisible] = useState(false); + const [userAckNonRegisteredState, setUserAckNonRegisteredState] = useState(false); + const disallowSignTx = useDisallowSignTx(request); useEffect(() => { const getVotingProcedures = async () => { @@ -24,54 +30,69 @@ export const VotingProceduresContainer = (): React.ReactElement => { getVotingProcedures(); }, [request]); + useEffect(() => { + if (!walletState?.transactions.history || userAckNonRegisteredState) return; + setIsNonRegisteredUserModalVisible(hasValidDrepRegistration(walletState.transactions.history)); + }, [walletState?.transactions.history, userAckNonRegisteredState]); + const explorerBaseUrl = useCexplorerBaseUrl(); return ( - { - const voterType = getVoterType(votingProcedure.voter.__typename); + <> + { + setUserAckNonRegisteredState(true); + setIsNonRegisteredUserModalVisible(false); + }} + onClose={() => disallowSignTx(true)} + /> + { + const voterType = getVoterType(votingProcedure.voter.__typename); - const drepId = - voterType === VoterTypeEnum.DREP - ? drepIDasBech32FromHash(votingProcedure.voter.credential.hash) - : votingProcedure.voter.credential.hash.toString(); - return { - voter: { - type: t(`core.VotingProcedures.voterTypes.${voterType}`), - dRepId: drepId - }, - votes: votingProcedure.votes.map((vote) => ({ - actionId: { - index: vote.actionId.actionIndex, - txHash: vote.actionId.id.toString(), - txHashUrl: `${explorerBaseUrl}/${vote.actionId.id}` + const drepId = + voterType === VoterTypeEnum.DREP + ? drepIDasBech32FromHash(votingProcedure.voter.credential.hash) + : votingProcedure.voter.credential.hash.toString(); + return { + voter: { + type: t(`core.VotingProcedures.voterTypes.${voterType}`), + dRepId: drepId }, - votingProcedure: { - vote: t(`core.VotingProcedures.votes.${getVote(vote.votingProcedure.vote)}`), - anchor: !!vote.votingProcedure.anchor?.url && { - url: vote.votingProcedure.anchor?.url, - hash: vote.votingProcedure.anchor?.dataHash.toString() + votes: votingProcedure.votes.map((vote) => ({ + actionId: { + index: vote.actionId.actionIndex, + txHash: vote.actionId.id.toString(), + txHashUrl: `${explorerBaseUrl}/${vote.actionId.id}` + }, + votingProcedure: { + vote: t(`core.VotingProcedures.votes.${getVote(vote.votingProcedure.vote)}`), + anchor: !!vote.votingProcedure.anchor?.url && { + url: vote.votingProcedure.anchor?.url, + hash: vote.votingProcedure.anchor?.dataHash.toString() + } } - } - })) - }; - })} - translations={{ - voterType: t('core.VotingProcedures.voterType'), - procedureTitle: t('core.VotingProcedures.procedureTitle'), - actionIdTitle: t('core.VotingProcedures.actionIdTitle'), - vote: t('core.VotingProcedures.vote'), - actionId: { - index: t('core.VotingProcedures.actionId.index'), - txHash: t('core.VotingProcedures.actionId.txHash') - }, - anchor: { - hash: t('core.VotingProcedures.anchor.hash'), - url: t('core.VotingProcedures.anchor.url') - }, - dRepId: t('core.VotingProcedures.dRepId') - }} - /> + })) + }; + })} + translations={{ + voterType: t('core.VotingProcedures.voterType'), + procedureTitle: t('core.VotingProcedures.procedureTitle'), + actionIdTitle: t('core.VotingProcedures.actionIdTitle'), + vote: t('core.VotingProcedures.vote'), + actionId: { + index: t('core.VotingProcedures.actionId.index'), + txHash: t('core.VotingProcedures.actionId.txHash') + }, + anchor: { + hash: t('core.VotingProcedures.anchor.hash'), + url: t('core.VotingProcedures.anchor.url') + }, + dRepId: t('core.VotingProcedures.dRepId') + }} + /> + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx index e8f382ee1c..4fb8d59f55 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx @@ -7,10 +7,13 @@ const mockUseWalletStore = jest.fn(); const t = jest.fn().mockImplementation((res) => res); const mockUseTranslation = jest.fn(() => ({ t })); const mockVotingProcedures = jest.fn(); +const mockNonRegisteredUserModal = jest.fn(); +const mockUseDisallowSignTx = jest.fn(); +const mockHasValidDrepRegistration = jest.fn(); const mockPreprodCexplorerBaseUrl = 'PREPROD_CEXPLORER_BASE_URL'; const mockCexplorerUrlPathsTx = 'CEXPLORER_URL_PATHS.TX'; import * as React from 'react'; -import { cleanup, render } from '@testing-library/react'; +import { cleanup, render, waitFor } from '@testing-library/react'; import { VotingProceduresContainer } from '../VotingProceduresContainer'; import '@testing-library/jest-dom'; import { act } from 'react-dom/test-utils'; @@ -47,6 +50,15 @@ jest.mock('@lace/core', () => { }; }); +jest.mock('../NonRegisteredUserModal/NonRegisteredUserModal', () => { + const original = jest.requireActual('../NonRegisteredUserModal/NonRegisteredUserModal'); + return { + __esModule: true, + ...original, + NonRegisteredUserModal: mockNonRegisteredUserModal + }; +}); + jest.mock('react-i18next', () => { const original = jest.requireActual('react-i18next'); return { @@ -56,6 +68,20 @@ jest.mock('react-i18next', () => { }; }); +jest.mock('../utils', () => ({ + ...jest.requireActual('../utils'), + hasValidDrepRegistration: mockHasValidDrepRegistration +})); + +jest.mock('../hooks', () => { + const original = jest.requireActual('../hooks'); + return { + __esModule: true, + ...original, + useDisallowSignTx: mockUseDisallowSignTx + }; +}); + const dappInfo = { name: 'dappName', logo: 'dappLogo', @@ -159,13 +185,13 @@ describe('Testing VotingProceduresContainer component', () => { })); mockVotingProcedures.mockReset(); mockVotingProcedures.mockReturnValue(); + mockNonRegisteredUserModal.mockReset(); + mockNonRegisteredUserModal.mockReturnValue(); mockUseTranslation.mockReset(); mockUseTranslation.mockImplementation(() => ({ t })); }); afterEach(() => { - jest.resetModules(); - jest.resetAllMocks(); cleanup(); }); @@ -225,6 +251,71 @@ describe('Testing VotingProceduresContainer component', () => { ); }); + test('should handle NonRegisteredUserModal onConfirm', async () => { + mockHasValidDrepRegistration.mockReset(); + mockHasValidDrepRegistration.mockReturnValue(true); + mockUseWalletStore.mockReset(); + mockUseWalletStore.mockImplementation(() => ({ + environmentName: 'Preprod', + walletState: { + transactions: { + history: [] + } + } + })); + + await act(async () => { + render(, { + wrapper: getWrapper() + }); + }); + + expect(mockNonRegisteredUserModal.mock.calls[mockNonRegisteredUserModal.mock.calls.length - 1][0].visible).toEqual( + true + ); + + await act(async () => { + mockNonRegisteredUserModal.mock.calls[mockNonRegisteredUserModal.mock.calls.length - 1][0].onConfirm(); + }); + + await waitFor(async () => { + expect( + mockNonRegisteredUserModal.mock.calls[mockNonRegisteredUserModal.mock.calls.length - 1][0].visible + ).toEqual(false); + }); + }); + + test('should handle NonRegisteredUserModal onClose', async () => { + const disallowSignTxMock = jest.fn(); + mockUseDisallowSignTx.mockReset(); + mockUseDisallowSignTx.mockReturnValue(disallowSignTxMock); + mockHasValidDrepRegistration.mockReset(); + mockHasValidDrepRegistration.mockReturnValue(true); + mockUseWalletStore.mockReset(); + mockUseWalletStore.mockImplementation(() => ({ + environmentName: 'Preprod', + walletState: { + transactions: { + history: [] + } + } + })); + + await act(async () => { + render(, { + wrapper: getWrapper() + }); + }); + + expect(disallowSignTxMock).not.toHaveBeenCalled(); + + await act(async () => { + mockNonRegisteredUserModal.mock.calls[mockNonRegisteredUserModal.mock.calls.length - 1][0].onClose(); + }); + + expect(disallowSignTxMock).toHaveBeenCalledWith(true); + }); + test('testing getVoterType', () => { expect(getVoterType(constitutionalCommitteeKeyHashVoter.__typename)).toEqual( VoterTypeEnum.CONSTITUTIONAL_COMMITTEE diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/utils.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/utils.test.tsx index 919dad9d21..ca920d6f46 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/utils.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/utils.test.tsx @@ -17,7 +17,8 @@ import { getTxType, drepIDasBech32FromHash, pubDRepKeyToHash, - depositPaidWithSymbol + depositPaidWithSymbol, + hasValidDrepRegistration } from '../utils'; jest.mock('@cardano-sdk/core', () => ({ @@ -170,4 +171,59 @@ describe('Testing utils', () => { 'coinId Unknown not supported' ); }); + + describe('hasValidDrepRegistration', () => { + test('should return false if there transactions', () => { + const transactions = [] as unknown as Wallet.Cardano.HydratedTx[]; + expect(hasValidDrepRegistration(transactions)).toBe(false); + }); + + test('should return false if there is no certificates', () => { + const transactions = [{ body: {} }, { body: { certificates: [] } }] as unknown as Wallet.Cardano.HydratedTx[]; + expect(hasValidDrepRegistration(transactions)).toBe(false); + }); + + test('should return true if first certificate has RegisterDelegateRepresentative __typename', () => { + const transactions = [ + { + body: { + certificates: [ + { __typename: Wallet.Cardano.CertificateType.RegisterDelegateRepresentative }, + { __typename: Wallet.Cardano.CertificateType.UnregisterDelegateRepresentative } + ] + } + }, + { + body: { + certificates: [ + { __typename: Wallet.Cardano.CertificateType.UnregisterDelegateRepresentative }, + { __typename: Wallet.Cardano.CertificateType.RegisterDelegateRepresentative } + ] + } + } + ] as unknown as Wallet.Cardano.HydratedTx[]; + expect(hasValidDrepRegistration(transactions)).toBe(true); + }); + test('should return false if first certificate has UnregisterDelegateRepresentative __typename', () => { + const transactions = [ + { + body: { + certificates: [ + { __typename: Wallet.Cardano.CertificateType.UnregisterDelegateRepresentative }, + { __typename: Wallet.Cardano.CertificateType.RegisterDelegateRepresentative } + ] + } + }, + { + body: { + certificates: [ + { __typename: Wallet.Cardano.CertificateType.RegisterDelegateRepresentative }, + { __typename: Wallet.Cardano.CertificateType.UnregisterDelegateRepresentative } + ] + } + } + ] as unknown as Wallet.Cardano.HydratedTx[]; + expect(hasValidDrepRegistration(transactions)).toBe(false); + }); + }); }); diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/hooks.ts b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/hooks.ts index 512f679521..dba2979910 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/hooks.ts +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/hooks.ts @@ -162,7 +162,7 @@ export const useCreateMintedAssetList = ({ export const useDisallowSignTx = ( req: TransactionWitnessRequest -): ((close?: boolean) => void) => useCallback(() => disallowSignTx(req), [req]); +): ((close?: boolean) => void) => useCallback((close) => disallowSignTx(req, close), [req]); export const useAllowSignTx = ( req: TransactionWitnessRequest diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/utils.ts b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/utils.ts index 5345ff4549..05e0a05e7b 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/utils.ts +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/utils.ts @@ -166,3 +166,18 @@ export const depositPaidWithSymbol = (deposit: bigint, coinId: Wallet.CoinId): s throw new Error(`coinId ${coinId.name} not supported`); } }; + +export const hasValidDrepRegistration = (history: Wallet.Cardano.HydratedTx[]): boolean => { + for (const transaction of history) { + const drepRegistrationOrRetirementCerticicate = transaction.body.certificates?.find((cert) => + [CertificateType.UnregisterDelegateRepresentative, CertificateType.RegisterDelegateRepresentative].includes( + cert.__typename + ) + ); + + if (drepRegistrationOrRetirementCerticicate) { + return drepRegistrationOrRetirementCerticicate.__typename === CertificateType.RegisterDelegateRepresentative; + } + } + return false; +}; diff --git a/apps/browser-extension-wallet/src/lib/translations/en.json b/apps/browser-extension-wallet/src/lib/translations/en.json index 484c9d56fa..ec84e58f91 100644 --- a/apps/browser-extension-wallet/src/lib/translations/en.json +++ b/apps/browser-extension-wallet/src/lib/translations/en.json @@ -1430,6 +1430,14 @@ "yes": "Yes", "no": "No", "abstain": "Abstain" + }, + "NonRegisteredUserModal": { + "title": "You're not a registered DRep", + "description": "Proceeding with this vote won't have any impact. Do you still want to proceed?", + "cta": { + "ok": "Proceed anyway", + "cancel": "Cancel" + } } }, "DRepRegistration": { From 202459611537d14f7794da6ff270c63932ddbfc3 Mon Sep 17 00:00:00 2001 From: vetalcore Date: Mon, 4 Mar 2024 15:19:57 +0200 Subject: [PATCH 2/4] feat(extension): fix modal visibility condition --- .../confirm-transaction/VotingProceduresContainer.tsx | 2 +- .../__tests__/VotingProceduresContainer.test.tsx | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx index 87eaebc6d7..c9e32f6abf 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx @@ -32,7 +32,7 @@ export const VotingProceduresContainer = (): React.ReactElement => { useEffect(() => { if (!walletState?.transactions.history || userAckNonRegisteredState) return; - setIsNonRegisteredUserModalVisible(hasValidDrepRegistration(walletState.transactions.history)); + setIsNonRegisteredUserModalVisible(!hasValidDrepRegistration(walletState.transactions.history)); }, [walletState?.transactions.history, userAckNonRegisteredState]); const explorerBaseUrl = useCexplorerBaseUrl(); diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx index 4fb8d59f55..0c7f5e648c 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx @@ -179,6 +179,8 @@ jest.mock('@providers', () => ({ describe('Testing VotingProceduresContainer component', () => { beforeEach(() => { + mockHasValidDrepRegistration.mockReset(); + mockHasValidDrepRegistration.mockReturnValue(true); mockUseWalletStore.mockReset(); mockUseWalletStore.mockImplementation(() => ({ environmentName: 'Preprod' @@ -253,7 +255,7 @@ describe('Testing VotingProceduresContainer component', () => { test('should handle NonRegisteredUserModal onConfirm', async () => { mockHasValidDrepRegistration.mockReset(); - mockHasValidDrepRegistration.mockReturnValue(true); + mockHasValidDrepRegistration.mockReturnValue(false); mockUseWalletStore.mockReset(); mockUseWalletStore.mockImplementation(() => ({ environmentName: 'Preprod', From 55ae91cc40e17707ee32c10662fabf375fcaa3b2 Mon Sep 17 00:00:00 2001 From: vetalcore Date: Mon, 4 Mar 2024 15:22:12 +0200 Subject: [PATCH 3/4] feat(extension): fix test --- .../__tests__/VotingProceduresContainer.test.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx index 0c7f5e648c..bfb5f96462 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/VotingProceduresContainer.test.tsx @@ -292,7 +292,7 @@ describe('Testing VotingProceduresContainer component', () => { mockUseDisallowSignTx.mockReset(); mockUseDisallowSignTx.mockReturnValue(disallowSignTxMock); mockHasValidDrepRegistration.mockReset(); - mockHasValidDrepRegistration.mockReturnValue(true); + mockHasValidDrepRegistration.mockReturnValue(false); mockUseWalletStore.mockReset(); mockUseWalletStore.mockImplementation(() => ({ environmentName: 'Preprod', From fc84952cd0a2b205ea9f8b65306424757041b874 Mon Sep 17 00:00:00 2001 From: vetalcore Date: Mon, 4 Mar 2024 15:40:01 +0200 Subject: [PATCH 4/4] fix(extension): resolve pr comments --- .../VotingProceduresContainer.tsx | 16 ++++++---------- .../dapp/components/confirm-transaction/utils.ts | 6 ++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx index c9e32f6abf..771506372b 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/VotingProceduresContainer.tsx @@ -1,9 +1,9 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; import { VotingProcedures } from '@lace/core'; -import { drepIDasBech32FromHash, hasValidDrepRegistration, votingProceduresInspector } from './utils'; +import { getDRepId, hasValidDrepRegistration, votingProceduresInspector } from './utils'; import { useCexplorerBaseUrl, useDisallowSignTx } from './hooks'; -import { VoterTypeEnum, getVote, getVoterType } from '@src/utils/tx-inspection'; +import { getVote, getVoterType } from '@src/utils/tx-inspection'; import { Wallet } from '@lace/cardano'; import { NonRegisteredUserModal } from './NonRegisteredUserModal/NonRegisteredUserModal'; import { useViewsFlowContext } from '@providers'; @@ -52,14 +52,10 @@ export const VotingProceduresContainer = (): React.ReactElement => { data={votingProcedures.map((votingProcedure) => { const voterType = getVoterType(votingProcedure.voter.__typename); - const drepId = - voterType === VoterTypeEnum.DREP - ? drepIDasBech32FromHash(votingProcedure.voter.credential.hash) - : votingProcedure.voter.credential.hash.toString(); return { voter: { type: t(`core.VotingProcedures.voterTypes.${voterType}`), - dRepId: drepId + dRepId: getDRepId(votingProcedure.voter) }, votes: votingProcedure.votes.map((vote) => ({ actionId: { @@ -69,9 +65,9 @@ export const VotingProceduresContainer = (): React.ReactElement => { }, votingProcedure: { vote: t(`core.VotingProcedures.votes.${getVote(vote.votingProcedure.vote)}`), - anchor: !!vote.votingProcedure.anchor?.url && { - url: vote.votingProcedure.anchor?.url, - hash: vote.votingProcedure.anchor?.dataHash.toString() + anchor: !!vote.votingProcedure.anchor && { + url: vote.votingProcedure.anchor.url, + hash: vote.votingProcedure.anchor.dataHash.toString() } } })) diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/utils.ts b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/utils.ts index 05e0a05e7b..aa50a42c26 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/utils.ts +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/utils.ts @@ -7,6 +7,7 @@ import type { UserPromptService } from '@lib/scripts/background/services'; import { DAPP_CHANNELS, cardanoCoin } from '@src/utils/constants'; import { runtime } from 'webextension-polyfill'; import { of } from 'rxjs'; +import { VoterTypeEnum, getVoterType } from '@src/utils/tx-inspection'; const { CertificateType } = Wallet.Cardano; @@ -181,3 +182,8 @@ export const hasValidDrepRegistration = (history: Wallet.Cardano.HydratedTx[]): } return false; }; + +export const getDRepId = (voter: Wallet.Cardano.Voter): Wallet.Cardano.DRepID | string => + getVoterType(voter.__typename) === VoterTypeEnum.DREP + ? drepIDasBech32FromHash(voter.credential.hash) + : voter.credential.hash.toString();