From 9cfb48dfa27defc376cc6851fe888e7c0a1c19e9 Mon Sep 17 00:00:00 2001 From: Tom Mayel Date: Tue, 21 May 2024 10:36:09 +0100 Subject: [PATCH] refactor(core): squash all commits to fix CI --- .github/workflows/chromatic-core.yml | 2 +- .github/workflows/chromatic-staking.yml | 2 +- .github/workflows/chromatic-ui.yml | 2 +- .github/workflows/ci.yml | 6 +- .github/workflows/e2e-tests-win.yml | 2 +- .github/workflows/sonar-cloud.yml | 2 +- apps/browser-extension-wallet/.env.defaults | 3 + .../.env.developerpreview | 3 + apps/browser-extension-wallet/.env.example | 3 + .../ConfirmDRepRegistrationContainer.tsx | 40 +- .../ConfirmDRepRetirementContainer.tsx | 30 +- .../ConfirmDRepUpdateContainer.tsx | 35 +- ...rmStakeRegistrationDelegationContainer.tsx | 37 +- .../ConfirmStakeVoteDelegationContainer.tsx | 46 +- ...akeVoteRegistrationDelegationContainer.tsx | 48 +- .../ConfirmVoteDelegationContainer.tsx | 40 +- ...irmVoteRegistrationDelegationContainer.tsx | 41 +- .../ProposalProceduresContainer.tsx | 15 +- .../VotingProceduresContainer.tsx | 60 +- .../ConfirmDRepRegistrationContainer.test.tsx | 16 +- .../ConfirmDRepRetirementContainer.test.tsx | 14 +- .../ConfirmDRepUpdateContainer.test.tsx | 14 +- ...keRegistrationDelegationContainer.test.tsx | 9 - ...nfirmStakeVoteDelegationContainer.test.tsx | 15 +- ...teRegistrationDelegationContainer.test.tsx | 17 +- .../ConfirmVoteDelegationContainer.test.tsx | 33 +- ...teRegistrationDelegationContainer.test.tsx | 16 +- .../ProposalProceduresContainer.test.tsx | 2 +- .../VotingProceduresContainer.test.tsx | 48 +- .../__tests__/utils.test.tsx | 15 +- .../HardForkInitiationActionContainer.tsx | 83 +- .../InfoActionContainer.tsx | 42 +- .../NewConstitutionActionContainer.tsx | 89 +- .../NoConfidenceActionContainer.tsx | 72 +- .../ParameterChangeActionContainer.tsx | 366 -------- .../ParameterChangeActionContainer.tsx | 42 + .../ParameterChangeActionContainer/index.ts | 1 + .../TreasuryWithdrawalsActionContainer.tsx | 83 +- .../UpdateCommitteeActionContainer.tsx | 97 +-- ...HardForkInitiationActionContainer.test.tsx | 38 +- .../__tests__/InfoActionContainer.test.tsx | 44 +- .../NewConstitutionActionContainer.test.tsx | 43 +- .../NoConfidenceActionContainer.test.tsx | 35 +- .../ParameterChangeActionContainer.test.tsx | 223 +---- ...reasuryWithdrawalsActionContainer.test.tsx | 38 +- .../UpdateCommitteeActionContainer.test.tsx | 50 +- .../components/confirm-transaction/utils.ts | 22 +- .../analyticsTracker/events.ts | 2 +- .../analyticsTracker/types.ts | 9 +- .../src/routes/wallet-paths.ts | 19 +- .../stores/slices/activity-detail-slice.ts | 20 +- .../src/types/activity-detail.ts | 13 +- .../src/utils/tx-inspection.ts | 41 +- .../TopUpWallet/TopUpWallet.module.scss | 35 + .../TopUpWallet/TopUpWalletButton.tsx | 44 + .../TopUpWallet/TopUpWalletCard.tsx | 33 + .../TopUpWallet/TopUpWalletDialog.tsx | 52 ++ .../components/TopUpWallet/config.ts | 3 + .../components/TopUpWallet/index.ts | 2 + .../views/browser-view/components/index.ts | 1 + .../components/TransactionDetailsProxy.tsx | 16 +- .../activity/helpers/common-tx-transformer.ts | 577 +------------ .../features/assets/components/Assets.tsx | 21 +- .../AssetsPortfolio.module.scss | 6 +- .../AssetsPortfolio/AssetsPortfolio.tsx | 26 +- .../multi-wallet/{components => }/Home.tsx | 8 +- .../features/multi-wallet/MultiWallet.tsx | 116 +-- .../multi-wallet/WalletOnboardingFlows.tsx | 56 ++ .../create-wallet/CreateWallet.test.tsx | 85 +- .../create-wallet/CreateWallet.tsx | 29 +- .../multi-wallet/create-wallet/context.tsx | 60 +- .../create-wallet/steps/NewRecoveryPhrase.tsx | 30 +- .../create-wallet/steps/Setup.tsx | 5 +- .../multi-wallet/create-wallet/types.ts | 12 +- .../hardware-wallet/ErrorDialog.module.scss | 38 + .../hardware-wallet/ErrorDialog.tsx | 47 +- .../hardware-wallet/HardwareWallet.test.tsx | 33 +- .../hardware-wallet/HardwareWallet.tsx | 29 +- .../multi-wallet/hardware-wallet/context.tsx | 64 +- .../hardware-wallet/steps/Connect.tsx | 13 +- .../hardware-wallet/steps/Setup.tsx | 7 +- .../multi-wallet/hardware-wallet/types.ts | 6 + .../restore-wallet/RestoreWallet.test.tsx | 33 +- .../restore-wallet/RestoreWallet.tsx | 27 +- .../multi-wallet/restore-wallet/context.tsx | 81 +- .../steps/RestoreRecoveryPhrase.tsx | 11 +- .../restore-wallet/steps/Setup.tsx | 13 +- .../multi-wallet/restore-wallet/types.ts | 12 +- .../features/multi-wallet/types.ts | 7 + .../multi-wallet/useHotWalletCreation.ts | 5 + .../multi-wallet/walletOnboardingContext.tsx | 20 + .../send-transaction/components/Form/Form.tsx | 4 +- .../wallet-setup/components/WalletSetup.tsx | 129 +-- .../components/WalletSetupMainPage.tsx | 16 +- .../components/WalletSetupWizard.tsx | 1 - packages/cardano/src/wallet/util/drep.ts | 7 + packages/cardano/src/wallet/util/index.ts | 2 + packages/cardano/src/wallet/util/voter.ts | 97 +++ packages/common/src/analytics/types.ts | 5 +- packages/core/.storybook/__mocks__/cardano.ts | 11 +- .../TransactionDetails.stories.tsx | 795 ++---------------- .../ActivityDetail/TransactionDetails.tsx | 278 +----- .../{TxDetailsList.tsx => TxDetailsGroup.tsx} | 37 +- .../__tests__/TransactionDetails.test.tsx | 13 +- .../components/DetailRow.module.scss | 45 - .../ActivityDetail/components/DetailRow.tsx | 31 - .../components/DetailRowSubitems.tsx | 16 - .../ActivityDetail/components/DetailRows.tsx | 47 -- .../ActivityDetail/components/InfoItem.tsx | 19 - .../TxDetailsCertificates/CertificateView.tsx | 154 ++++ .../TxDetailsCertificates.module.scss | 8 + .../TxDetailsCertificates.tsx | 37 + .../ProposalProcedureAction.tsx | 132 +++ .../TxDetailsProposalProcedures.tsx | 34 + .../TxDetailsProposalProcedures/index.ts | 1 + .../components/TxDetailsVotingProcedures.tsx | 27 + .../ActivityDetail/components/index.ts | 1 - .../AuthorizeCommitteeCertificate.tsx | 53 ++ .../AuthorizeCommitteeCertificate/index.ts | 1 + .../ConfirmDRepRegistration.stories.tsx | 20 - .../ConfirmDRepRegistration.tsx | 58 +- .../ConfirmDRepRetirement.stories.tsx | 18 - .../ConfirmDRepRetirement.tsx | 45 +- .../ConfirmDRepUpdate.stories.tsx | 20 - .../ConfirmDRepUpdate/ConfirmDRepUpdate.tsx | 48 +- ...irmStakeRegistrationDelegation.stories.tsx | 19 - .../ConfirmStakeRegistrationDelegation.tsx | 79 +- .../ConfirmStakeVoteDelegation.stories.tsx | 22 - .../ConfirmStakeVoteDelegation.tsx | 93 +- ...takeVoteRegistrationDelegation.stories.tsx | 23 - ...ConfirmStakeVoteRegistrationDelegation.tsx | 106 ++- .../ConfirmVoteDelegation.stories.tsx | 20 - .../ConfirmVoteDelegation.tsx | 49 +- ...firmVoteRegistrationDelegation.stories.tsx | 22 - .../ConfirmVoteRegistrationDelegation.tsx | 57 +- .../DappTransaction/DappTransaction.tsx | 11 +- .../core/src/ui/components/Nft/NftDetail.tsx | 1 + .../HardForkInitiationAction.stories.tsx | 38 - .../HardForkInitiationAction.tsx | 65 +- .../HardForkInitiationActionTypes.ts | 2 +- .../InfoAction/InfoAction.stories.tsx | 29 +- .../InfoAction/InfoAction.tsx | 57 +- .../InfoAction/InfoActionTypes.ts | 2 +- .../NewConstitutionAction.stories.tsx | 41 - .../NewConstitutionAction.tsx | 74 +- .../NewConstitutionActionTypes.ts | 2 +- .../NoConfidenceAction.stories.tsx | 33 - .../NoConfidenceAction/NoConfidenceAction.tsx | 66 +- .../NoConfidenceActionTypes.ts | 2 +- .../ParameterChangeAction.stories.tsx | 127 --- .../ParameterChangeAction.tsx | 312 +++++-- .../ParameterChangeActionTypes.ts | 2 +- .../TreasuryWithdrawalsAction.stories.tsx | 38 - .../TreasuryWithdrawalsAction.tsx | 125 +-- .../TreasuryWithdrawalsActionTypes.ts | 2 +- .../UpdateCommitteeActionAction.stories.tsx | 49 -- .../UpdateCommitteeActionAction.tsx | 177 ++-- .../UpdateCommitteeActionTypes.ts | 2 +- ...> ProposalProcedureTransactionDetails.tsx} | 23 +- ...oposalProcedureTransactionDetailsTypes.ts} | 1 - .../ResignCommitteeCertificate.tsx | 59 ++ .../ResignCommitteeCertificate/index.ts | 1 + .../VotingProcedures.stories.tsx | 117 +-- .../VotingProcedures/VotingProcedures.tsx | 69 +- .../WalletSetupConfirmationDialogProvider.tsx | 10 +- .../src/ui/utils/governance-action-mocks.ts | 221 +++++ .../core/src/ui/utils/governance-action.ts | 377 +++++++++ packages/core/src/ui/utils/index.ts | 2 + .../src/ui/utils/voting-procedures-mock.ts | 52 ++ .../src/assert/topNavigationAssert.ts | 5 + .../src/assert/transactionsPageAssert.ts | 23 + .../e2e-tests/src/elements/NFTs/nftDetails.ts | 19 +- .../src/elements/transactionsPage.ts | 21 + .../src/features/NFTsExtended.feature | 12 +- .../e2e-tests/src/features/NFTsPopup.feature | 11 + .../src/features/TransactionsExtended.feature | 15 + .../src/features/TransactionsPopup.feature | 15 + .../e2e-tests/src/steps/navigationTopSteps.ts | 6 + .../e2e-tests/src/steps/nftsCommonSteps.ts | 5 + .../e2e-tests/src/steps/nftsExtendedSteps.ts | 16 +- .../e2e-tests/src/steps/transactionsSteps.ts | 19 + .../e2e-tests/src/types/transactionStyle.ts | 1 + .../e2e-tests/src/types/transactionType.ts | 8 + .../icons/raw/ada.component-transparent.svg | 3 + .../browser-extension-wallet/en.json | 12 + .../buttons/call-to-action-button.css.ts | 2 +- .../buttons/call-to-action-button.tsx | 1 + .../dialog/dialog-action.component.tsx | 11 +- ...profile-dropdown-wallet-card.component.tsx | 6 +- .../user-profile.component.tsx | 9 +- 190 files changed, 3689 insertions(+), 5171 deletions(-) delete mode 100644 apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer.tsx create mode 100644 apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer/ParameterChangeActionContainer.tsx create mode 100644 apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer/index.ts create mode 100644 apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWallet.module.scss create mode 100644 apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletButton.tsx create mode 100644 apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletCard.tsx create mode 100644 apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletDialog.tsx create mode 100644 apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/config.ts create mode 100644 apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/index.ts rename apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/{components => }/Home.tsx (90%) create mode 100644 apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/WalletOnboardingFlows.tsx create mode 100644 apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/ErrorDialog.module.scss create mode 100644 apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/types.ts create mode 100644 apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/walletOnboardingContext.tsx create mode 100644 packages/cardano/src/wallet/util/drep.ts create mode 100644 packages/cardano/src/wallet/util/voter.ts rename packages/core/src/ui/components/ActivityDetail/{TxDetailsList.tsx => TxDetailsGroup.tsx} (57%) delete mode 100644 packages/core/src/ui/components/ActivityDetail/components/DetailRow.module.scss delete mode 100644 packages/core/src/ui/components/ActivityDetail/components/DetailRow.tsx delete mode 100644 packages/core/src/ui/components/ActivityDetail/components/DetailRowSubitems.tsx delete mode 100644 packages/core/src/ui/components/ActivityDetail/components/DetailRows.tsx delete mode 100644 packages/core/src/ui/components/ActivityDetail/components/InfoItem.tsx create mode 100644 packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/CertificateView.tsx create mode 100644 packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/TxDetailsCertificates.module.scss create mode 100644 packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/TxDetailsCertificates.tsx create mode 100644 packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/ProposalProcedureAction.tsx create mode 100644 packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/TxDetailsProposalProcedures.tsx create mode 100644 packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/index.ts create mode 100644 packages/core/src/ui/components/ActivityDetail/components/TxDetailsVotingProcedures.tsx delete mode 100644 packages/core/src/ui/components/ActivityDetail/components/index.ts create mode 100644 packages/core/src/ui/components/AuthorizeCommitteeCertificate/AuthorizeCommitteeCertificate.tsx create mode 100644 packages/core/src/ui/components/AuthorizeCommitteeCertificate/index.ts rename packages/core/src/ui/components/ProposalProcedures/components/{TransactionDetails.tsx => ProposalProcedureTransactionDetails.tsx} (51%) rename packages/core/src/ui/components/ProposalProcedures/components/{TransactionDetailsTypes.ts => ProposalProcedureTransactionDetailsTypes.ts} (91%) create mode 100644 packages/core/src/ui/components/ResignCommitteeCertificate/ResignCommitteeCertificate.tsx create mode 100644 packages/core/src/ui/components/ResignCommitteeCertificate/index.ts create mode 100644 packages/core/src/ui/utils/governance-action-mocks.ts create mode 100644 packages/core/src/ui/utils/governance-action.ts create mode 100644 packages/core/src/ui/utils/voting-procedures-mock.ts create mode 100644 packages/e2e-tests/src/types/transactionStyle.ts create mode 100644 packages/e2e-tests/src/types/transactionType.ts create mode 100644 packages/icons/raw/ada.component-transparent.svg diff --git a/.github/workflows/chromatic-core.yml b/.github/workflows/chromatic-core.yml index 24c6d3298..906493034 100644 --- a/.github/workflows/chromatic-core.yml +++ b/.github/workflows/chromatic-core.yml @@ -19,7 +19,7 @@ jobs: chromatic-deployment: name: Chromatic Core if: github.event.pull_request.draft == false - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/chromatic-staking.yml b/.github/workflows/chromatic-staking.yml index 1e645cbc9..f087ce588 100644 --- a/.github/workflows/chromatic-staking.yml +++ b/.github/workflows/chromatic-staking.yml @@ -19,7 +19,7 @@ jobs: chromatic-deployment: name: Chromatic Staking if: github.event.pull_request.draft == false - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/chromatic-ui.yml b/.github/workflows/chromatic-ui.yml index 0f640e0cf..7658124ef 100644 --- a/.github/workflows/chromatic-ui.yml +++ b/.github/workflows/chromatic-ui.yml @@ -19,7 +19,7 @@ jobs: chromatic-deployment: name: Chromatic UI if: github.event.pull_request.draft == false - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1d667bfa1..1529d1458 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,7 +18,7 @@ concurrency: jobs: prepare: name: Prepare - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repository @@ -80,7 +80,7 @@ jobs: unitTests: name: Unit tests - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 needs: prepare steps: @@ -144,7 +144,7 @@ jobs: smokeTests: name: Smoke tests - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 needs: prepare steps: diff --git a/.github/workflows/e2e-tests-win.yml b/.github/workflows/e2e-tests-win.yml index 4fe450521..af2bd1ec3 100644 --- a/.github/workflows/e2e-tests-win.yml +++ b/.github/workflows/e2e-tests-win.yml @@ -146,7 +146,7 @@ jobs: publish-reports-linux: if: always() needs: run-tests-windows - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 steps: - name: Checkout repository uses: actions/checkout@v4 diff --git a/.github/workflows/sonar-cloud.yml b/.github/workflows/sonar-cloud.yml index beb9d06ef..56c41e1b0 100644 --- a/.github/workflows/sonar-cloud.yml +++ b/.github/workflows/sonar-cloud.yml @@ -14,7 +14,7 @@ concurrency: jobs: sonarcloud: name: SonarCloud Code Analysis - runs-on: ubuntu-22.04 + runs-on: ubuntu-20.04 steps: - uses: actions/checkout@v4 with: diff --git a/apps/browser-extension-wallet/.env.defaults b/apps/browser-extension-wallet/.env.defaults index 27f71189c..5c90c2189 100644 --- a/apps/browser-extension-wallet/.env.defaults +++ b/apps/browser-extension-wallet/.env.defaults @@ -28,6 +28,7 @@ USE_MULTI_DELEGATION_STAKING_ACTIVITY=true USE_MULTI_DELEGATION_STAKING_GRID_VIEW=true USE_MULTI_DELEGATION_STAKING_FILTERS=false USE_ROS_STAKING_COLUMN=false +USE_FOOR_TOPUP=false USE_POSTHOG_ANALYTICS_FOR_OPTED_OUT=false USE_MULTI_WALLET=true @@ -48,6 +49,8 @@ PRIVACY_POLICY_URL=https://www.lace.io/iog-privacy-policy.pdf COOKIE_POLICY_URL=https://www.lace.io/lace-cookie-policy.pdf TERMS_OF_USE_URL=https://www.lace.io/lace-terms-of-use.pdf YOUTUBE_RECOVERY_PHRASE_VIDEO_URL=https://www.youtube-nocookie.com/embed/hOFVXo969rk?si=0a-hNDVME6eTboIX +BANXA_LACE_URL=https://lacewallet.banxa-sandbox.com/ +BANXA_HOMEPAGE_URL=https://banxa.com/ # events tracking PUBLIC_POSTHOG_HOST=https://eu.posthog.com diff --git a/apps/browser-extension-wallet/.env.developerpreview b/apps/browser-extension-wallet/.env.developerpreview index eb03eed73..374ef90a4 100644 --- a/apps/browser-extension-wallet/.env.developerpreview +++ b/apps/browser-extension-wallet/.env.developerpreview @@ -28,6 +28,7 @@ USE_MULTI_DELEGATION_STAKING_TREZOR=false USE_MULTI_DELEGATION_STAKING_ACTIVITY=true USE_MULTI_DELEGATION_STAKING_GRID_VIEW=true USE_ROS_STAKING_COLUMN=false +USE_FOOR_TOPUP=false USE_POSTHOG_ANALYTICS_FOR_OPTED_OUT=false USE_MULTI_WALLET=false @@ -48,6 +49,8 @@ PRIVACY_POLICY_URL=https://www.lace.io/iog-privacy-policy.pdf COOKIE_POLICY_URL=https://www.lace.io/lace-cookie-policy.pdf TERMS_OF_USE_URL=https://www.lace.io/lace-terms-of-use.pdf YOUTUBE_RECOVERY_PHRASE_VIDEO_URL=https://www.youtube-nocookie.com/embed/hOFVXo969rk?si=0a-hNDVME6eTboIX +BANXA_LACE_URL=https://lacewallet.banxa-sandbox.com/ +BANXA_HOMEPAGE_URL=https://banxa.com/ # events tracking PUBLIC_POSTHOG_HOST=https://eu.posthog.com diff --git a/apps/browser-extension-wallet/.env.example b/apps/browser-extension-wallet/.env.example index 95774ded0..17bfdafdf 100644 --- a/apps/browser-extension-wallet/.env.example +++ b/apps/browser-extension-wallet/.env.example @@ -28,6 +28,7 @@ USE_MULTI_DELEGATION_STAKING_ACTIVITY=true USE_MULTI_DELEGATION_STAKING_GRID_VIEW=true USE_MULTI_DELEGATION_STAKING_FILTERS=false USE_ROS_STAKING_COLUMN=false +USE_FOOR_TOPUP=false # In App URLs CATALYST_GOOGLE_PLAY_URL=https://play.google.com/store/apps/details?id=io.iohk.vitvoting @@ -44,6 +45,8 @@ PRIVACY_POLICY_URL=https://www.lace.io/iog-privacy-policy.pdf COOKIE_POLICY_URL=https://www.lace.io/lace-cookie-policy.pdf TERMS_OF_USE_URL=https://www.lace.io/lace-terms-of-use.pdf YOUTUBE_RECOVERY_PHRASE_VIDEO_URL=https://www.youtube-nocookie.com/embed/hOFVXo969rk?si=0a-hNDVME6eTboIX +BANXA_LACE_URL=https://lacewallet.banxa-sandbox.com/ +BANXA_HOMEPAGE_URL=https://banxa.com/ # events tracking PUBLIC_POSTHOG_HOST=https://eu.posthog.com # set this variable to true only in release packages. By having this set to false, we ensure that we will not be using Post Hog production projects tokens in development stage diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepRegistrationContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepRegistrationContainer.tsx index 7cba19e55..fa62aa0cf 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepRegistrationContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepRegistrationContainer.tsx @@ -1,16 +1,15 @@ import React, { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { ConfirmDRepRegistration } from '@lace/core'; -import { certificateInspectorFactory, depositPaidWithSymbol, drepIDasBech32FromHash } from './utils'; +import { ConfirmDRepRegistration, DappInfo } from '@lace/core'; +import { certificateInspectorFactory, depositPaidWithSymbol } from './utils'; import { Wallet } from '@lace/cardano'; import { useWalletStore } from '@src/stores'; import { useViewsFlowContext } from '@providers'; import { Skeleton } from 'antd'; +import { Box, Flex } from '@lace/ui'; const { CertificateType } = Wallet.Cardano; export const ConfirmDRepRegistrationContainer = (): React.ReactElement => { - const { t } = useTranslation(); const { walletUI: { cardanoCoin } } = useWalletStore(); @@ -37,26 +36,19 @@ export const ConfirmDRepRegistrationContainer = (): React.ReactElement => { } const depositPaidWithCardanoSymbol = depositPaidWithSymbol(certificate.deposit, cardanoCoin); - - // TODO: might be changed in scope of https://input-output.atlassian.net/browse/LW-9034 return ( - + + + + + + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepRetirementContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepRetirementContainer.tsx index 2a146d782..7b81109f3 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepRetirementContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepRetirementContainer.tsx @@ -1,13 +1,14 @@ import React, { useCallback, useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { ConfirmDRepRetirement } from '@lace/core'; -import { certificateInspectorFactory, depositPaidWithSymbol, disallowSignTx, drepIDasBech32FromHash } from './utils'; +import { ConfirmDRepRetirement, DappInfo } from '@lace/core'; +import { certificateInspectorFactory, depositPaidWithSymbol, disallowSignTx } from './utils'; import { Wallet } from '@lace/cardano'; import { useWalletStore } from '@src/stores'; import { useGetOwnPubDRepKeyHash } from './hooks'; import { Skeleton } from 'antd'; import { DappError } from '../DappError'; import { useViewsFlowContext } from '@providers'; +import { Box, Flex } from '@lace/ui'; const { CertificateType } = Wallet.Cardano; @@ -75,19 +76,16 @@ export const ConfirmDRepRetirementContainer = ({ onError }: Props): React.ReactE } return ( - + + + + + + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepUpdateContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepUpdateContainer.tsx index 691529f97..8382b4eb7 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepUpdateContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmDRepUpdateContainer.tsx @@ -1,15 +1,14 @@ import React, { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { ConfirmDRepUpdate } from '@lace/core'; -import { certificateInspectorFactory, drepIDasBech32FromHash } from './utils'; +import { ConfirmDRepUpdate, DappInfo } from '@lace/core'; +import { certificateInspectorFactory } from './utils'; import { Wallet } from '@lace/cardano'; import { useViewsFlowContext } from '@providers'; import { Skeleton } from 'antd'; +import { Box, Flex } from '@lace/ui'; const { CertificateType } = Wallet.Cardano; export const ConfirmDRepUpdateContainer = (): React.ReactElement => { - const { t } = useTranslation(); const { signTxRequest: { request }, dappInfo @@ -32,21 +31,17 @@ export const ConfirmDRepUpdateContainer = (): React.ReactElement => { } return ( - + + + + + + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeRegistrationDelegationContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeRegistrationDelegationContainer.tsx index 0d991fbf1..46417caee 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeRegistrationDelegationContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeRegistrationDelegationContainer.tsx @@ -1,11 +1,12 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { ConfirmStakeRegistrationDelegation } from '@lace/core'; +import { ConfirmStakeRegistrationDelegation, DappInfo } from '@lace/core'; import { certificateInspectorFactory, depositPaidWithSymbol } from './utils'; import { Wallet } from '@lace/cardano'; import { useWalletStore } from '@src/stores'; import { useViewsFlowContext } from '@providers'; import { Skeleton } from 'antd'; +import { Box, Flex, TransactionSummary } from '@lace/ui'; const { CertificateType, RewardAddress } = Wallet.Cardano; @@ -36,24 +37,22 @@ export const ConfirmStakeRegistrationDelegationContainer = (): React.ReactElemen return ; } const depositPaidWithCardanoSymbol = depositPaidWithSymbol(certificate.deposit, cardanoCoin); + return ( - + + + + + + + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeVoteDelegationContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeVoteDelegationContainer.tsx index df1b8eca7..4be3d8a95 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeVoteDelegationContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeVoteDelegationContainer.tsx @@ -1,16 +1,15 @@ import React, { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { ConfirmStakeVoteDelegation } from '@lace/core'; -import { certificateInspectorFactory, drepIDasBech32FromHash } from './utils'; +import { ConfirmStakeVoteDelegation, DappInfo } from '@lace/core'; +import { certificateInspectorFactory } from './utils'; import { Wallet } from '@lace/cardano'; import { useWalletStore } from '@src/stores'; import { useViewsFlowContext } from '@providers'; import { Skeleton } from 'antd'; +import { Box } from '@lace/ui'; const { CertificateType, RewardAddress } = Wallet.Cardano; export const ConfirmStakeVoteDelegationContainer = (): React.ReactElement => { - const { t } = useTranslation(); const { currentChain } = useWalletStore(); const { signTxRequest: { request }, @@ -36,28 +35,21 @@ export const ConfirmStakeVoteDelegationContainer = (): React.ReactElement => { const dRep = certificate.dRep; return ( - + <> + + + + + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeVoteRegistrationDelegationContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeVoteRegistrationDelegationContainer.tsx index 55fcd6639..36c98c94f 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeVoteRegistrationDelegationContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmStakeVoteRegistrationDelegationContainer.tsx @@ -1,11 +1,12 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { ConfirmStakeVoteRegistrationDelegation } from '@lace/core'; -import { certificateInspectorFactory, depositPaidWithSymbol, drepIDasBech32FromHash } from './utils'; +import { ConfirmStakeVoteRegistrationDelegation, DappInfo } from '@lace/core'; +import { certificateInspectorFactory, depositPaidWithSymbol } from './utils'; import { Wallet } from '@lace/cardano'; import { useWalletStore } from '@src/stores'; import { useViewsFlowContext } from '@providers'; import { Skeleton } from 'antd'; +import { Box, Flex, TransactionSummary } from '@lace/ui'; const { CertificateType, RewardAddress } = Wallet.Cardano; @@ -41,30 +42,23 @@ export const ConfirmStakeVoteRegistrationDelegationContainer = (): React.ReactEl const depositPaidWithCardanoSymbol = depositPaidWithSymbol(certificate.deposit, cardanoCoin); return ( - + + + + + + + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmVoteDelegationContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmVoteDelegationContainer.tsx index 8590fd0fe..815ba5474 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmVoteDelegationContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmVoteDelegationContainer.tsx @@ -1,15 +1,14 @@ import React, { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { ConfirmVoteDelegation } from '@lace/core'; -import { certificateInspectorFactory, drepIDasBech32FromHash } from './utils'; +import { ConfirmVoteDelegation, DappInfo } from '@lace/core'; +import { certificateInspectorFactory } from './utils'; import { Wallet } from '@lace/cardano'; import { useViewsFlowContext } from '@providers'; import { Skeleton } from 'antd'; +import { Box, Flex } from '@lace/ui'; const { CertificateType } = Wallet.Cardano; export const ConfirmVoteDelegationContainer = (): React.ReactElement => { - const { t } = useTranslation(); const { signTxRequest: { request }, dappInfo @@ -34,24 +33,19 @@ export const ConfirmVoteDelegationContainer = (): React.ReactElement => { const { dRep } = certificate; return ( - + + + + + + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmVoteRegistrationDelegationContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmVoteRegistrationDelegationContainer.tsx index 60a84e13b..0e9e7a71f 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmVoteRegistrationDelegationContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ConfirmVoteRegistrationDelegationContainer.tsx @@ -1,11 +1,12 @@ import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { ConfirmVoteRegistrationDelegation } from '@lace/core'; -import { certificateInspectorFactory, depositPaidWithSymbol, drepIDasBech32FromHash } from './utils'; +import { ConfirmVoteRegistrationDelegation, DappInfo } from '@lace/core'; +import { certificateInspectorFactory, depositPaidWithSymbol } from './utils'; import { Wallet } from '@lace/cardano'; import { useWalletStore } from '@src/stores'; import { useViewsFlowContext } from '@providers'; import { Skeleton } from 'antd'; +import { Box, Flex, TransactionSummary } from '@lace/ui'; const { CertificateType, RewardAddress } = Wallet.Cardano; @@ -41,26 +42,20 @@ export const ConfirmVoteRegistrationDelegationContainer = (): React.ReactElement const depositPaidWithCardanoSymbol = depositPaidWithSymbol(deposit, cardanoCoin); return ( - + + + + + + + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ProposalProceduresContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ProposalProceduresContainer.tsx index b72eb6d91..6022c9a51 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ProposalProceduresContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/ProposalProceduresContainer.tsx @@ -9,7 +9,8 @@ import { ParameterChangeActionContainer } from './proposal-procedures/ParameterC import { TreasuryWithdrawalsActionContainer } from './proposal-procedures/TreasuryWithdrawalsActionContainer'; import { UpdateCommitteeActionContainer } from './proposal-procedures/UpdateCommitteeActionContainer'; import { useViewsFlowContext } from '@providers'; -import { SignTxData } from './types'; +import { Box, Flex } from '@lace/ui'; +import { DappInfo } from '@lace/core'; export const ProposalProceduresContainer = (): React.ReactElement => { const [proposalProcedures, setProposalProcedures] = useState([]); @@ -30,12 +31,10 @@ export const ProposalProceduresContainer = (): React.ReactElement => { const containerPerTypeMap: Record< Wallet.Cardano.GovernanceActionType, (props: { - dappInfo: SignTxData['dappInfo']; governanceAction: Wallet.Cardano.GovernanceAction; deposit: Wallet.Cardano.ProposalProcedure['deposit']; rewardAccount: Wallet.Cardano.ProposalProcedure['rewardAccount']; anchor: Wallet.Cardano.ProposalProcedure['anchor']; - errorMessage?: string; }) => React.ReactElement > = useMemo( () => ({ @@ -55,10 +54,12 @@ export const ProposalProceduresContainer = (): React.ReactElement => { {proposalProcedures.map(({ deposit, rewardAccount, anchor, governanceAction }) => { const Container = containerPerTypeMap[governanceAction.__typename]; return ( - + + + + + + ); })} 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 fbe3515f7..10b19bdb8 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,17 +1,15 @@ import React, { useEffect, useState } from 'react'; -import { useTranslation } from 'react-i18next'; -import { VotingProcedures } from '@lace/core'; -import { getDRepId, votingProceduresInspector } from './utils'; +import { DappInfo, VotingProcedures } from '@lace/core'; +import { votingProceduresInspector } from './utils'; import { useCexplorerBaseUrl, useDisallowSignTx } from './hooks'; -import { 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'; +import { Box, Flex } from '@lace/ui'; export const VotingProceduresContainer = (): React.ReactElement => { - const { t } = useTranslation(); const { signTxRequest: { request }, dappInfo @@ -54,48 +52,16 @@ export const VotingProceduresContainer = (): React.ReactElement => { }} onClose={() => disallowSignTx(true)} /> - { - const voterType = getVoterType(votingProcedure.voter.__typename); - - return { - voter: { - type: t(`core.VotingProcedures.voterTypes.${voterType}`), - dRepId: getDRepId(votingProcedure.voter) - }, - 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: 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') - }} - /> + + + + + + Wallet.util.mapVotingProcedureToView(votingProcedure, explorerBaseUrl) + )} + /> + ); }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepRegistrationContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepRegistrationContainer.test.tsx index 1dc94ae50..19f1454fa 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepRegistrationContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepRegistrationContainer.test.tsx @@ -14,10 +14,10 @@ import { act } from 'react-dom/test-utils'; import { buildMockTx } from '@src/utils/mocks/tx'; import { Wallet } from '@lace/cardano'; import { getWrapper } from '../testing.utils'; -import { depositPaidWithSymbol, drepIDasBech32FromHash } from '../utils'; +import { depositPaidWithSymbol } from '../utils'; import { TransactionWitnessRequest } from '@cardano-sdk/web-extension'; -const { Cardano, Crypto } = Wallet; +const { Cardano, Crypto, util } = Wallet; const assetInfo$ = new BehaviorSubject(new Map()); const available$ = new BehaviorSubject([]); @@ -127,21 +127,11 @@ describe('Testing ConfirmDRepRegistrationContainer component', () => { expect(queryByTestId('ConfirmDRepRegistration')).toBeInTheDocument(); expect(mockConfirmDRepRegistration).toHaveBeenLastCalledWith( { - dappInfo, metadata: { depositPaid: depositPaidWithSymbol(certificate.deposit, cardanoCoinMock as Wallet.CoinId), - drepId: drepIDasBech32FromHash(certificate.dRepCredential.hash), + drepId: util.drepIDasBech32FromHash(certificate.dRepCredential.hash), hash: certificate.anchor?.dataHash, url: certificate.anchor?.url - }, - translations: { - metadata: t('core.DRepRegistration.metadata'), - labels: { - depositPaid: t('core.DRepRegistration.depositPaid'), - drepId: t('core.DRepRegistration.drepId'), - hash: t('core.DRepRegistration.hash'), - url: t('core.DRepRegistration.url') - } } }, {} diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepRetirementContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepRetirementContainer.test.tsx index ac55acc54..714315d3f 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepRetirementContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepRetirementContainer.test.tsx @@ -21,10 +21,10 @@ import { act } from 'react-dom/test-utils'; import { buildMockTx } from '@src/utils/mocks/tx'; import { Wallet } from '@lace/cardano'; import { getWrapper } from '../testing.utils'; -import { depositPaidWithSymbol, drepIDasBech32FromHash } from '../utils'; +import { depositPaidWithSymbol } from '../utils'; import { TransactionWitnessRequest } from '@cardano-sdk/web-extension'; -const { Cardano, Crypto } = Wallet; +const { Cardano, Crypto, util } = Wallet; const assetInfo$ = new BehaviorSubject(new Map()); const available$ = new BehaviorSubject([]); @@ -173,17 +173,9 @@ describe('Testing ConfirmDRepRetirementContainer component', () => { expect(queryByTestId('ConfirmDRepRetirementContainer')).toBeInTheDocument(); expect(mockConfirmDRepRetirement).toHaveBeenLastCalledWith( { - dappInfo, metadata: { depositReturned: depositPaidWithSymbol(certificate.deposit, cardanoCoinMock as Wallet.CoinId), - drepId: drepIDasBech32FromHash(certificate.dRepCredential.hash) - }, - translations: { - metadata: t('core.DRepRetirement.metadata'), - labels: { - depositReturned: t('core.DRepRetirement.depositReturned'), - drepId: t('core.DRepRetirement.drepId') - } + drepId: util.drepIDasBech32FromHash(certificate.dRepCredential.hash) } }, {} diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepUpdateContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepUpdateContainer.test.tsx index 650361e93..6cb2fc485 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepUpdateContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmDRepUpdateContainer.test.tsx @@ -14,10 +14,9 @@ import { act } from 'react-dom/test-utils'; import { buildMockTx } from '@src/utils/mocks/tx'; import { Wallet } from '@lace/cardano'; import { getWrapper } from '../testing.utils'; -import { drepIDasBech32FromHash } from '../utils'; import { TransactionWitnessRequest } from '@cardano-sdk/web-extension'; -const { Cardano, Crypto } = Wallet; +const { Cardano, Crypto, util } = Wallet; const assetInfo$ = new BehaviorSubject(new Map()); const available$ = new BehaviorSubject([]); @@ -126,19 +125,10 @@ describe('Testing ConfirmDRepUpdateContainer component', () => { expect(queryByTestId('ConfirmDRepUpdate')).toBeInTheDocument(); expect(mockConfirmDRepUpdate).toHaveBeenLastCalledWith( { - dappInfo, metadata: { - drepId: drepIDasBech32FromHash(certificate.dRepCredential.hash), + drepId: util.drepIDasBech32FromHash(certificate.dRepCredential.hash), hash: certificate.anchor?.dataHash, url: certificate.anchor?.url - }, - translations: { - metadata: t('core.DRepUpdate.metadata'), - labels: { - drepId: t('core.DRepUpdate.drepId'), - hash: t('core.DRepUpdate.hash'), - url: t('core.DRepUpdate.url') - } } }, {} diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeRegistrationDelegationContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeRegistrationDelegationContainer.test.tsx index 318361616..a07869d10 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeRegistrationDelegationContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeRegistrationDelegationContainer.test.tsx @@ -145,19 +145,10 @@ describe('Testing ConfirmStakeRegistrationDelegationContainer component', () => expect(queryByTestId('ConfirmStakeRegistrationDelegation')).toBeInTheDocument(); expect(mockConfirmStakeRegistrationDelegation).toHaveBeenLastCalledWith( { - dappInfo, metadata: { poolId: certificate.poolId, stakeKeyHash: 'stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj', depositPaid: depositPaidWithSymbol(certificate.deposit, cardanoCoinMock as Wallet.CoinId) - }, - translations: { - metadata: t('core.StakeRegistrationDelegation.metadata'), - labels: { - poolId: t('core.StakeRegistrationDelegation.poolId'), - stakeKeyHash: t('core.StakeRegistrationDelegation.stakeKeyHash'), - depositPaid: t('core.StakeRegistrationDelegation.depositPaid') - } } }, {} diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeVoteDelegationContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeVoteDelegationContainer.test.tsx index 3de25766c..fb6aba120 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeVoteDelegationContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeVoteDelegationContainer.test.tsx @@ -17,7 +17,6 @@ import { act } from 'react-dom/test-utils'; import { buildMockTx } from '@src/utils/mocks/tx'; import { Wallet } from '@lace/cardano'; import { getWrapper } from '../testing.utils'; -import { drepIDasBech32FromHash } from '../utils'; import { TransactionWitnessRequest } from '@cardano-sdk/web-extension'; const REWARD_ACCOUNT = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); @@ -160,24 +159,12 @@ describe('Testing ConfirmStakeVoteDelegationContainer component', () => { expect(queryByTestId('ConfirmStakeVoteDelegation')).toBeInTheDocument(); expect(mockConfirmStakeVoteDelegation).toHaveBeenLastCalledWith( { - dappInfo, metadata: { poolId: certificate.poolId, stakeKeyHash: 'stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj', alwaysAbstain: isDRepAlwaysAbstainMocked, alwaysNoConfidence: isDRepAlwaysNoConfidenceMocked, - drepId: drepIDasBech32FromHash((certificate.dRep as Wallet.Cardano.Credential).hash) - }, - translations: { - metadata: t('core.StakeVoteDelegation.metadata'), - option: t('core.StakeVoteDelegation.option'), - labels: { - poolId: t('core.StakeVoteDelegation.poolId'), - stakeKeyHash: t('core.StakeVoteDelegation.stakeKeyHash'), - drepId: t('core.StakeVoteDelegation.drepId'), - alwaysAbstain: t('core.StakeVoteDelegation.alwaysAbstain'), - alwaysNoConfidence: t('core.StakeVoteDelegation.alwaysNoConfidence') - } + drepId: Wallet.util.drepIDasBech32FromHash((certificate.dRep as Wallet.Cardano.Credential).hash) } }, {} diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeVoteRegistrationDelegationContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeVoteRegistrationDelegationContainer.test.tsx index 1528d4542..8a230d446 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeVoteRegistrationDelegationContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmStakeVoteRegistrationDelegationContainer.test.tsx @@ -18,7 +18,7 @@ import { act } from 'react-dom/test-utils'; import { buildMockTx } from '@src/utils/mocks/tx'; import { Wallet } from '@lace/cardano'; import { getWrapper } from '../testing.utils'; -import { depositPaidWithSymbol, drepIDasBech32FromHash } from '../utils'; +import { depositPaidWithSymbol } from '../utils'; import { TransactionWitnessRequest } from '@cardano-sdk/web-extension'; const REWARD_ACCOUNT = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); @@ -169,26 +169,13 @@ describe('Testing ConfirmStakeVoteRegistrationDelegationContainer component', () expect(queryByTestId('ConfirmStakeVoteRegistrationDelegation')).toBeInTheDocument(); expect(mockConfirmStakeVoteRegistrationDelegation).toHaveBeenLastCalledWith( { - dappInfo, metadata: { poolId: certificate.poolId, stakeKeyHash: 'stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj', depositPaid: depositPaidWithSymbol(certificate.deposit, cardanoCoinMock as Wallet.CoinId), alwaysAbstain: isDRepAlwaysAbstainMocked, alwaysNoConfidence: isDRepAlwaysNoConfidenceMocked, - drepId: drepIDasBech32FromHash((certificate.dRep as Wallet.Cardano.Credential).hash) - }, - translations: { - metadata: t('core.StakeVoteDelegationRegistration.metadata'), - option: t('core.StakeVoteDelegationRegistration.option'), - labels: { - poolId: t('core.StakeVoteDelegationRegistration.poolId'), - stakeKeyHash: t('core.StakeVoteDelegationRegistration.stakeKeyHash'), - drepId: t('core.StakeVoteDelegationRegistration.drepId'), - alwaysAbstain: t('core.StakeVoteDelegationRegistration.alwaysAbstain'), - alwaysNoConfidence: t('core.StakeVoteDelegationRegistration.alwaysNoConfidence'), - depositPaid: t('core.StakeVoteDelegationRegistration.depositPaid') - } + drepId: Wallet.util.drepIDasBech32FromHash((certificate.dRep as Wallet.Cardano.Credential).hash) } }, {} diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmVoteDelegationContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmVoteDelegationContainer.test.tsx index 0f2083c18..6a682dca5 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmVoteDelegationContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmVoteDelegationContainer.test.tsx @@ -16,7 +16,6 @@ import { act } from 'react-dom/test-utils'; import { buildMockTx } from '@src/utils/mocks/tx'; import { Wallet } from '@lace/cardano'; import { getWrapper } from '../testing.utils'; -import { drepIDasBech32FromHash } from '../utils'; const REWARD_ACCOUNT = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); const STAKE_KEY_HASH = Wallet.Cardano.RewardAccount.toHash(REWARD_ACCOUNT); @@ -132,20 +131,10 @@ describe('Testing ConfirmVoteDelegationContainer component', () => { expect(queryByTestId('ConfirmVoteDelegation')).toBeInTheDocument(); expect(mockConfirmVoteDelegation).toHaveBeenLastCalledWith( { - dappInfo, metadata: { alwaysAbstain: false, alwaysNoConfidence: false, - drepId: drepIDasBech32FromHash((dRep as unknown as Wallet.Cardano.Credential).hash) - }, - translations: { - metadata: t('core.VoteDelegation.metadata'), - option: t('core.VoteDelegation.option'), - labels: { - drepId: t('core.VoteDelegation.drepId'), - alwaysAbstain: t('core.VoteDelegation.alwaysAbstain'), - alwaysNoConfidence: t('core.VoteDelegation.alwaysNoConfidence') - } + drepId: Wallet.util.drepIDasBech32FromHash((dRep as unknown as Wallet.Cardano.Credential).hash) } }, {} @@ -187,19 +176,9 @@ describe('Testing ConfirmVoteDelegationContainer component', () => { expect(queryByTestId('ConfirmVoteDelegation')).toBeInTheDocument(); expect(mockConfirmVoteDelegation).toHaveBeenLastCalledWith( { - dappInfo, metadata: { alwaysAbstain: true, alwaysNoConfidence: false - }, - translations: { - metadata: t('core.VoteDelegation.metadata'), - option: t('core.VoteDelegation.option'), - labels: { - drepId: t('core.VoteDelegation.drepId'), - alwaysAbstain: t('core.VoteDelegation.alwaysAbstain'), - alwaysNoConfidence: t('core.VoteDelegation.alwaysNoConfidence') - } } }, {} @@ -241,19 +220,9 @@ describe('Testing ConfirmVoteDelegationContainer component', () => { expect(queryByTestId('ConfirmVoteDelegation')).toBeInTheDocument(); expect(mockConfirmVoteDelegation).toHaveBeenLastCalledWith( { - dappInfo, metadata: { alwaysAbstain: false, alwaysNoConfidence: true - }, - translations: { - metadata: t('core.VoteDelegation.metadata'), - option: t('core.VoteDelegation.option'), - labels: { - drepId: t('core.VoteDelegation.drepId'), - alwaysAbstain: t('core.VoteDelegation.alwaysAbstain'), - alwaysNoConfidence: t('core.VoteDelegation.alwaysNoConfidence') - } } }, {} diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmVoteRegistrationDelegationContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmVoteRegistrationDelegationContainer.test.tsx index cf88de426..96ef2038b 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmVoteRegistrationDelegationContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ConfirmVoteRegistrationDelegationContainer.test.tsx @@ -19,7 +19,7 @@ import { act } from 'react-dom/test-utils'; import { buildMockTx } from '@src/utils/mocks/tx'; import { Wallet } from '@lace/cardano'; import { getWrapper } from '../testing.utils'; -import { depositPaidWithSymbol, drepIDasBech32FromHash } from '../utils'; +import { depositPaidWithSymbol } from '../utils'; import { TransactionWitnessRequest } from '@cardano-sdk/web-extension'; const REWARD_ACCOUNT = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); @@ -167,24 +167,12 @@ describe('Testing ConfirmVoteRegistrationDelegationContainer component', () => { expect(queryByTestId('ConfirmVoteRegistrationDelegation')).toBeInTheDocument(); expect(mockConfirmVoteRegistrationDelegation).toHaveBeenLastCalledWith( { - dappInfo, metadata: { depositPaid: depositPaidWithSymbol(certificate.deposit, cardanoCoinMock as Wallet.CoinId), stakeKeyHash: 'stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj', alwaysAbstain: isDRepAlwaysAbstainMocked, alwaysNoConfidence: isDRepAlwaysNoConfidenceMocked, - drepId: drepIDasBech32FromHash((certificate.dRep as Wallet.Cardano.Credential).hash) - }, - translations: { - metadata: t('core.VoteRegistrationDelegation.metadata'), - option: t('core.VoteRegistrationDelegation.option'), - labels: { - drepId: t('core.VoteRegistrationDelegation.drepId'), - alwaysAbstain: t('core.VoteRegistrationDelegation.alwaysAbstain'), - alwaysNoConfidence: t('core.VoteRegistrationDelegation.alwaysNoConfidence'), - depositPaid: t('core.VoteRegistrationDelegation.depositPaid'), - stakeKeyHash: t('core.VoteRegistrationDelegation.stakeKeyHash') - } + drepId: Wallet.util.drepIDasBech32FromHash((certificate.dRep as Wallet.Cardano.Credential).hash) } }, {} diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ProposalProceduresContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ProposalProceduresContainer.test.tsx index 21faa2faa..d2acefc59 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ProposalProceduresContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/__tests__/ProposalProceduresContainer.test.tsx @@ -160,7 +160,7 @@ describe('Testing ProposalProceduresContainer component', () => { expect(queryByTestId('TreasuryWithdrawalsActionContainer')).toBeInTheDocument(); expect(queryByTestId('UpdateCommitteeActionContainer')).toBeInTheDocument(); - const expectedProps = { dappInfo, deposit, rewardAccount, anchor }; + const expectedProps = { deposit, rewardAccount, anchor }; expect(mockHardForkInitiationActionContainer).toHaveBeenLastCalledWith( { ...expectedProps, governanceAction: hardForkInitiationAction }, 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 6e14b70ef..c03dea66a 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 @@ -19,8 +19,6 @@ import { act } from 'react-dom/test-utils'; import { buildMockTx } from '@src/utils/mocks/tx'; import { Wallet } from '@lace/cardano'; import { getWrapper } from '../testing.utils'; -import { getVoterType, getVote, VoterTypeEnum, VotesEnum } from '@src/utils/tx-inspection'; -import { drepIDasBech32FromHash } from '../utils'; import { TransactionWitnessRequest } from '@cardano-sdk/web-extension'; import { of } from 'rxjs'; @@ -205,14 +203,13 @@ describe('Testing VotingProceduresContainer component', () => { expect(queryByTestId('VotingProcedures')).toBeInTheDocument(); // eslint-disable-next-line unicorn/consistent-function-scoping const getExpectedDrepId = (type: string) => (hash: Wallet.Crypto.Hash28ByteBase16) => - type === VoterTypeEnum.DREP ? drepIDasBech32FromHash(hash) : hash.toString(); + type === Wallet.util.VoterTypeEnum.DREP ? Wallet.util.drepIDasBech32FromHash(hash) : hash.toString(); expect(mockVotingProcedures).toHaveBeenLastCalledWith( { - dappInfo, data: voters.map(({ __typename }, index) => ({ voter: { - type: t(`core.VotingProcedures.voterTypes.${getVoterType(__typename)}`), - dRepId: getExpectedDrepId(getVoterType(__typename))(voters[index].credential.hash) + type: Wallet.util.getVoterType(__typename), + dRepId: getExpectedDrepId(Wallet.util.getVoterType(__typename))(voters[index].credential.hash) }, votes: votingProcedures[index].votes.map((vote) => ({ actionId: { @@ -221,29 +218,14 @@ describe('Testing VotingProceduresContainer component', () => { txHashUrl: `${mockPreprodCexplorerBaseUrl}/${mockCexplorerUrlPathsTx}/${vote.actionId.id}` }, votingProcedure: { - vote: t(`core.VotingProcedures.votes.${getVote(vote.votingProcedure.vote)}`), + vote: Wallet.util.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') - } + })) }, {} ); @@ -311,20 +293,20 @@ describe('Testing VotingProceduresContainer component', () => { }); test('testing getVoterType', () => { - expect(getVoterType(constitutionalCommitteeKeyHashVoter.__typename)).toEqual( - VoterTypeEnum.CONSTITUTIONAL_COMMITTEE + expect(Wallet.util.getVoterType(constitutionalCommitteeKeyHashVoter.__typename)).toEqual( + Wallet.util.VoterTypeEnum.CONSTITUTIONAL_COMMITTEE ); - expect(getVoterType(constitutionalCommitteeScriptHashVoter.__typename)).toEqual( - VoterTypeEnum.CONSTITUTIONAL_COMMITTEE + expect(Wallet.util.getVoterType(constitutionalCommitteeScriptHashVoter.__typename)).toEqual( + Wallet.util.VoterTypeEnum.CONSTITUTIONAL_COMMITTEE ); - expect(getVoterType(drepKeyHashVoter.__typename)).toEqual(VoterTypeEnum.DREP); - expect(getVoterType(drepScriptHashVoter.__typename)).toEqual(VoterTypeEnum.DREP); - expect(getVoterType(stakePoolKeyHashVoter.__typename)).toEqual(VoterTypeEnum.SPO); + expect(Wallet.util.getVoterType(drepKeyHashVoter.__typename)).toEqual(Wallet.util.VoterTypeEnum.DREP); + expect(Wallet.util.getVoterType(drepScriptHashVoter.__typename)).toEqual(Wallet.util.VoterTypeEnum.DREP); + expect(Wallet.util.getVoterType(stakePoolKeyHashVoter.__typename)).toEqual(Wallet.util.VoterTypeEnum.SPO); }); test('testing getVote', () => { - expect(getVote(Wallet.Cardano.Vote.yes)).toEqual(VotesEnum.YES); - expect(getVote(Wallet.Cardano.Vote.no)).toEqual(VotesEnum.NO); - expect(getVote(Wallet.Cardano.Vote.abstain)).toEqual(VotesEnum.ABSTAIN); + expect(Wallet.util.getVote(Wallet.Cardano.Vote.yes)).toEqual(Wallet.util.VotesEnum.YES); + expect(Wallet.util.getVote(Wallet.Cardano.Vote.no)).toEqual(Wallet.util.VotesEnum.NO); + expect(Wallet.util.getVote(Wallet.Cardano.Vote.abstain)).toEqual(Wallet.util.VotesEnum.ABSTAIN); }); }); 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 919dad9d2..2e3bc31cd 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 @@ -1,6 +1,5 @@ /* eslint-disable unicorn/consistent-function-scoping */ /* eslint-disable import/imports-first */ -const mockDRepID = jest.fn(); const mockHexBlob = (val: string) => val; mockHexBlob.toTypedBech32 = (prefix: string, value: string) => `${prefix}${value}`; /* eslint-disable unicorn/no-useless-undefined */ @@ -15,7 +14,6 @@ import { certificateInspectorFactory, votingProceduresInspector, getTxType, - drepIDasBech32FromHash, pubDRepKeyToHash, depositPaidWithSymbol } from '../utils'; @@ -33,8 +31,7 @@ jest.mock('@lace/cardano', () => { Wallet: { ...actual.Wallet, Cardano: { - ...actual.Wallet.Cardano, - DRepID: mockDRepID + ...actual.Wallet.Cardano }, HexBlob: mockHexBlob, Crypto: { @@ -149,11 +146,11 @@ describe('Testing utils', () => { }); test('testing drepIDasBech32FromHash', () => { - mockDRepID.mockReset(); - mockDRepID.mockImplementation((val) => val); - - const drepID = '_drepID'; - expect(drepIDasBech32FromHash(drepID as Wallet.Crypto.Hash28ByteBase16)).toEqual(`drep${drepID}`); + expect( + Wallet.util.drepIDasBech32FromHash( + '8293d319ef5b3ac72366dd28006bd315b715f7e7cfcbd3004129b80d' as Wallet.Crypto.Hash28ByteBase16 + ) + ).toEqual('drep1s2faxx00tvavwgmxm55qq67nzkm3tal8el9axqzp9xuq6s8s0wp'); }); test('testing pubDRepKeyToHash', async () => { diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/HardForkInitiationActionContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/HardForkInitiationActionContainer.tsx index af62be524..5eed36800 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/HardForkInitiationActionContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/HardForkInitiationActionContainer.tsx @@ -1,95 +1,40 @@ import React, { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; import { Wallet } from '@lace/cardano'; -import { HardForkInitiationAction } from '@lace/core'; +import { HardForkInitiationAction, getHardForkInitiationActionViewData } from '@lace/core'; import { useWalletStore } from '@src/stores'; -import { SignTxData } from '../types'; import { useCexplorerBaseUrl } from '../hooks'; interface Props { - dappInfo: SignTxData['dappInfo']; governanceAction: Wallet.Cardano.HardForkInitiationAction; deposit: Wallet.Cardano.ProposalProcedure['deposit']; rewardAccount: Wallet.Cardano.ProposalProcedure['rewardAccount']; anchor: Wallet.Cardano.ProposalProcedure['anchor']; - errorMessage?: string; } export const HardForkInitiationActionContainer = ({ - dappInfo, governanceAction, deposit, rewardAccount, - anchor, - errorMessage + anchor }: Props): React.ReactElement => { - const { t } = useTranslation(); const { walletUI: { cardanoCoin } } = useWalletStore(); const explorerBaseUrl = useCexplorerBaseUrl(); - const translations = useMemo[0]['translations']>( - () => ({ - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - protocolVersion: { - major: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.major'), - minor: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.minor'), - patch: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.patch') - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - } - }), - [t] - ); - - const { governanceActionId, protocolVersion } = governanceAction; - - const data: Parameters[0]['data'] = { - txDetails: { - txType: t('core.ProposalProcedure.governanceAction.hardForkInitiation.title'), - deposit: Wallet.util.getFormattedAmount({ - amount: deposit.toString(), - cardanoCoin + const data = useMemo( + () => + getHardForkInitiationActionViewData({ + anchor, + cardanoCoin, + deposit, + explorerBaseUrl, + governanceAction, + rewardAccount }), - rewardAccount - }, - procedure: { - anchor: { - url: anchor.url, - hash: anchor.dataHash, - txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` - } - }, - protocolVersion: { - major: protocolVersion.major.toString(), - minor: protocolVersion.minor.toString() - }, - ...(governanceActionId && { - actionId: { - index: governanceActionId.actionIndex.toString(), - id: governanceActionId.id || '' - } - }) - }; - - return ( - + [anchor, cardanoCoin, deposit, explorerBaseUrl, governanceAction, rewardAccount] ); + + return ; }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/InfoActionContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/InfoActionContainer.tsx index f880b2b86..d209532bb 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/InfoActionContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/InfoActionContainer.tsx @@ -1,50 +1,16 @@ import React, { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; import { Wallet } from '@lace/cardano'; -import { InfoAction } from '@lace/core'; -import { SignTxData } from '../types'; +import { InfoAction, getInfoActionViewData } from '@lace/core'; import { useCexplorerBaseUrl } from '../hooks'; interface Props { - dappInfo: SignTxData['dappInfo']; anchor: Wallet.Cardano.ProposalProcedure['anchor']; - errorMessage?: string; } -export const InfoActionContainer = ({ dappInfo, anchor, errorMessage }: Props): React.ReactElement => { - const { t } = useTranslation(); - +export const InfoActionContainer = ({ anchor }: Props): React.ReactElement => { const explorerBaseUrl = useCexplorerBaseUrl(); - const translations = useMemo[0]['translations']>( - () => ({ - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - } - }), - [t] - ); - - const data: Parameters[0]['data'] = { - txDetails: { - txType: t('core.ProposalProcedure.governanceAction.infoAction.title') - }, - procedure: { - anchor: { - url: anchor.url, - hash: anchor.dataHash, - txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` - } - } - }; + const data = useMemo(() => getInfoActionViewData({ anchor, explorerBaseUrl }), [anchor, explorerBaseUrl]); - return ; + return ; }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/NewConstitutionActionContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/NewConstitutionActionContainer.tsx index aef32fb04..ebc07f273 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/NewConstitutionActionContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/NewConstitutionActionContainer.tsx @@ -1,101 +1,40 @@ import React, { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; import { Wallet } from '@lace/cardano'; -import { NewConstitutionAction } from '@lace/core'; +import { NewConstitutionAction, getNewConstitutionActionViewData } from '@lace/core'; import { useWalletStore } from '@src/stores'; -import { SignTxData } from '../types'; import { useCexplorerBaseUrl } from '../hooks'; interface Props { - dappInfo: SignTxData['dappInfo']; governanceAction: Wallet.Cardano.NewConstitution; deposit: Wallet.Cardano.ProposalProcedure['deposit']; rewardAccount: Wallet.Cardano.ProposalProcedure['rewardAccount']; anchor: Wallet.Cardano.ProposalProcedure['anchor']; - errorMessage?: string; } export const NewConstitutionActionContainer = ({ - dappInfo, governanceAction, deposit, rewardAccount, - anchor, - errorMessage + anchor }: Props): React.ReactElement => { - const { t } = useTranslation(); const { walletUI: { cardanoCoin } } = useWalletStore(); const explorerBaseUrl = useCexplorerBaseUrl(); - const translations = useMemo[0]['translations']>( - () => ({ - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - constitution: { - title: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.title'), - anchor: { - dataHash: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.anchor.dataHash'), - url: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.anchor.url') - }, - scriptHash: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.scriptHash') - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - } - }), - [t] - ); - - const { governanceActionId, constitution } = governanceAction; - - const data: Parameters[0]['data'] = { - txDetails: { - txType: t('core.ProposalProcedure.governanceAction.newConstitutionAction.title'), - deposit: Wallet.util.getFormattedAmount({ - amount: deposit.toString(), - cardanoCoin + const data = useMemo( + () => + getNewConstitutionActionViewData({ + anchor, + cardanoCoin, + deposit, + explorerBaseUrl, + governanceAction, + rewardAccount }), - rewardAccount - }, - procedure: { - anchor: { - url: anchor.url, - hash: anchor.dataHash, - txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` - } - }, - ...(governanceActionId && { - actionId: { - index: governanceActionId.actionIndex.toString(), - id: governanceActionId.id || '' - } - }), - constitution: { - anchor: { - dataHash: constitution.anchor.dataHash.toString(), - url: constitution.anchor.url.toString() - }, - ...(constitution.scriptHash && { scriptHash: constitution.scriptHash.toString() }) - } - }; - - return ( - + [anchor, cardanoCoin, deposit, explorerBaseUrl, governanceAction, rewardAccount] ); + + return ; }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/NoConfidenceActionContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/NoConfidenceActionContainer.tsx index b7abdb9ce..cfc6b8606 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/NoConfidenceActionContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/NoConfidenceActionContainer.tsx @@ -1,84 +1,40 @@ import React, { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; import { Wallet } from '@lace/cardano'; -import { NoConfidenceAction } from '@lace/core'; +import { NoConfidenceAction, getNoConfidenceActionViewData } from '@lace/core'; import { useWalletStore } from '@src/stores'; -import { SignTxData } from '../types'; import { useCexplorerBaseUrl } from '../hooks'; interface Props { - dappInfo: SignTxData['dappInfo']; governanceAction: Wallet.Cardano.NoConfidence; deposit: Wallet.Cardano.ProposalProcedure['deposit']; rewardAccount: Wallet.Cardano.ProposalProcedure['rewardAccount']; anchor: Wallet.Cardano.ProposalProcedure['anchor']; - errorMessage?: string; } export const NoConfidenceActionContainer = ({ - dappInfo, governanceAction, deposit, rewardAccount, - anchor, - errorMessage + anchor }: Props): React.ReactElement => { - const { t } = useTranslation(); const { walletUI: { cardanoCoin } } = useWalletStore(); const explorerBaseUrl = useCexplorerBaseUrl(); - const translations = useMemo[0]['translations']>( - () => ({ - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - } - }), - [t] - ); - - const { governanceActionId } = governanceAction; - - const data: Parameters[0]['data'] = { - txDetails: { - txType: t('core.ProposalProcedure.governanceAction.noConfidenceAction.title'), - deposit: Wallet.util.getFormattedAmount({ - amount: deposit.toString(), - cardanoCoin + const data = useMemo( + () => + getNoConfidenceActionViewData({ + anchor, + cardanoCoin, + deposit, + explorerBaseUrl, + governanceAction, + rewardAccount }), - rewardAccount - }, - procedure: { - anchor: { - url: anchor.url, - hash: anchor.dataHash, - txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` - } - }, - ...(governanceActionId && { - actionId: { - index: governanceActionId.actionIndex.toString(), - id: governanceActionId.id || '' - } - }) - }; + [anchor, cardanoCoin, deposit, explorerBaseUrl, governanceAction, rewardAccount] + ); - return ; + return ; }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer.tsx deleted file mode 100644 index 55cc6a5c8..000000000 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer.tsx +++ /dev/null @@ -1,366 +0,0 @@ -/* eslint-disable unicorn/no-array-reduce */ -import React, { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; -import { formatPercentages } from '@lace/common'; -import { Wallet } from '@lace/cardano'; -import { ParameterChangeAction } from '@lace/core'; -import { useWalletStore } from '@src/stores'; -import { SignTxData } from '../types'; -import { useCexplorerBaseUrl } from '../hooks'; - -interface Props { - dappInfo: SignTxData['dappInfo']; - governanceAction: Wallet.Cardano.ParameterChangeAction; - deposit: Wallet.Cardano.ProposalProcedure['deposit']; - rewardAccount: Wallet.Cardano.ProposalProcedure['rewardAccount']; - anchor: Wallet.Cardano.ProposalProcedure['anchor']; - errorMessage?: string; -} - -export const ParameterChangeActionContainer = ({ - dappInfo, - governanceAction, - deposit, - rewardAccount, - anchor, - errorMessage -}: Props): React.ReactElement => { - const { t } = useTranslation(); - const { - walletUI: { cardanoCoin } - } = useWalletStore(); - - const explorerBaseUrl = useCexplorerBaseUrl(); - - // TODO: consider encapsulating it inside the component itself, check if all the translations have the fallback to the parent int provider (LW-9920) - const translations = useMemo[0]['translations']>( - () => ({ - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - }, - memory: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.memory'), - step: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.step'), - networkGroup: { - title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.title'), - maxBBSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBBSize'), - maxTxSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxTxSize'), - maxBHSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBHSize'), - maxValSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxValSize'), - maxTxExUnits: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxTxExUnits'), - maxBlockExUnits: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBlockExUnits'), - maxCollateralInputs: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxCollateralInputs' - ), - tooltip: { - maxBBSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBBSize'), - maxTxSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxTxSize'), - maxBHSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBHSize'), - maxValSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxValSize'), - maxTxExUnits: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxTxExUnits' - ), - maxBlockExUnits: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBlockExUnits' - ), - maxCollateralInputs: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxCollateralInputs' - ) - } - }, - economicGroup: { - title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.title'), - minFeeA: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minFeeA'), - minFeeB: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minFeeB'), - keyDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.keyDeposit'), - poolDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.poolDeposit'), - rho: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.rho'), - tau: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tau'), - minPoolCost: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minPoolCost'), - coinsPerUTxOByte: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.coinsPerUTxOByte' - ), - prices: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.prices'), - tooltip: { - minFeeA: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minFeeA'), - minFeeB: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minFeeB'), - keyDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.keyDeposit'), - poolDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.poolDeposit' - ), - rho: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.rho'), - tau: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.tau'), - minPoolCost: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minPoolCost' - ), - coinsPerUTxOByte: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.coinsPerUTxOByte' - ), - prices: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.prices') - } - }, - technicalGroup: { - title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.title'), - a0: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.a0'), - eMax: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.eMax'), - nOpt: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.nOpt'), - costModels: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.costModels'), - collateralPercentage: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.collateralPercentage' - ), - tooltip: { - a0: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.a0'), - eMax: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.eMax'), - nOpt: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.nOpt'), - costModels: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.costModels' - ), - collateralPercentage: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.collateralPercentage' - ) - } - }, - governanceGroup: { - title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.title'), - govActionLifetime: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.govActionLifetime' - ), - govActionDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.govActionDeposit' - ), - drepDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.drepDeposit'), - drepActivity: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.drepActivity'), - ccMinSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.ccMinSize'), - ccMaxTermLength: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.ccMaxTermLength' - ), - dRepVotingThresholds: { - title: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.title' - ), - motionNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.motionNoConfidence' - ), - committeeNormal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.committeeNormal' - ), - committeeNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.committeeNoConfidence' - ), - updateConstitution: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.updateConstitution' - ), - hardForkInitiation: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.hardForkInitiation' - ), - ppNetworkGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppNetworkGroup' - ), - ppEconomicGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppEconomicGroup' - ), - ppTechnicalGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppTechnicalGroup' - ), - ppGovernanceGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppGovernanceGroup' - ), - treasuryWithdrawal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.treasuryWithdrawal' - ) - }, - tooltip: { - govActionLifetime: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.govActionLifetime' - ), - govActionDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.govActionDeposit' - ), - drepDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.drepDeposit' - ), - drepActivity: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.drepActivity' - ), - ccMinSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.ccMinSize'), - ccMaxTermLength: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.ccMaxTermLength' - ), - dRepVotingThresholds: { - title: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.title' - ), - motionNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.motionNoConfidence' - ), - committeeNormal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.committeeNormal' - ), - committeeNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.committeeNoConfidence' - ), - updateConstitution: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.updateConstitution' - ), - hardForkInitiation: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.hardForkInitiation' - ), - ppNetworkGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppNetworkGroup' - ), - ppEconomicGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppEconomicGroup' - ), - ppTechnicalGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppTechnicalGroup' - ), - ppGovernanceGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppGovernanceGroup' - ), - treasuryWithdrawal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.treasuryWithdrawal' - ) - } - } - } - }), - [t] - ); - - const { - protocolParamUpdate: { - maxBlockBodySize, - maxTxSize, - maxBlockHeaderSize, - maxValueSize, - maxExecutionUnitsPerTransaction, - maxExecutionUnitsPerBlock, - maxCollateralInputs, - stakeKeyDeposit, - poolDeposit, - minFeeCoefficient, - minFeeConstant, - treasuryExpansion, - monetaryExpansion, - minPoolCost, - coinsPerUtxoByte, - prices, - poolInfluence, - poolRetirementEpochBound, - desiredNumberOfPools, - costModels, - collateralPercentage, - governanceActionDeposit, - dRepDeposit, - governanceActionValidityPeriod, - dRepInactivityPeriod, - minCommitteeSize, - committeeTermLimit, - dRepVotingThresholds: { - motionNoConfidence, - committeeNormal, - commiteeNoConfidence, - updateConstitution, - hardForkInitiation, - ppNetworkGroup, - ppEconomicGroup, - ppTechnicalGroup, - ppGovernanceGroup, - treasuryWithdrawal - } - } - } = governanceAction; - - const data: Parameters[0]['data'] = { - txDetails: { - txType: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.title'), - deposit: Wallet.util.getFormattedAmount({ - amount: deposit.toString(), - cardanoCoin - }), - rewardAccount - }, - anchor: { - url: anchor.url, - hash: anchor.dataHash, - txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` - }, - protocolParamUpdate: { - maxTxExUnits: { - memory: maxExecutionUnitsPerTransaction.memory.toString(), - step: maxExecutionUnitsPerTransaction.steps.toString() - }, - maxBlockExUnits: { - memory: maxExecutionUnitsPerBlock.memory.toString(), - step: maxExecutionUnitsPerBlock.steps.toString() - }, - networkGroup: { - maxBBSize: maxBlockBodySize.toString(), - maxTxSize: maxTxSize.toString(), - maxBHSize: maxBlockHeaderSize.toString(), - maxValSize: maxValueSize.toString(), - maxCollateralInputs: maxCollateralInputs.toString() - }, - economicGroup: { - minFeeA: minFeeCoefficient.toString(), - minFeeB: minFeeConstant.toString(), - keyDeposit: stakeKeyDeposit.toString(), - poolDeposit: poolDeposit.toString(), - rho: monetaryExpansion, - tau: treasuryExpansion, - minPoolCost: minPoolCost.toString(), - coinsPerUTxOByte: coinsPerUtxoByte.toString(), - price: { - memory: prices.memory.toString(), - step: prices.steps.toString() - } - }, - technicalGroup: { - a0: poolInfluence, - eMax: poolRetirementEpochBound.toString(), - nOpt: desiredNumberOfPools.toString(), - costModels: { - PlutusV1: Object.entries(costModels.get(Wallet.Cardano.PlutusLanguageVersion.V1)).reduce( - (acc, cur) => ({ ...acc, [cur[0]]: cur[1] }), - {} - ), - PlutusV2: Object.entries(costModels.get(Wallet.Cardano.PlutusLanguageVersion.V2)).reduce( - (acc, cur) => ({ ...acc, [cur[0]]: cur[1] }), - {} - ) - }, - collateralPercentage: collateralPercentage.toString() - }, - governanceGroup: { - govActionLifetime: governanceActionValidityPeriod.toString(), - govActionDeposit: governanceActionDeposit.toString(), - drepDeposit: dRepDeposit.toString(), - drepActivity: dRepInactivityPeriod.toString(), - ccMinSize: minCommitteeSize.toString(), - ccMaxTermLength: committeeTermLimit.toString(), - dRepVotingThresholds: { - motionNoConfidence: formatPercentages(motionNoConfidence.numerator / motionNoConfidence.denominator), - committeeNormal: formatPercentages(committeeNormal.numerator / committeeNormal.denominator), - committeeNoConfidence: formatPercentages(commiteeNoConfidence.numerator / commiteeNoConfidence.denominator), - updateToConstitution: formatPercentages(updateConstitution.numerator / updateConstitution.denominator), - hardForkInitiation: formatPercentages(hardForkInitiation.numerator / hardForkInitiation.denominator), - ppNetworkGroup: formatPercentages(ppNetworkGroup.numerator / ppNetworkGroup.denominator), - ppEconomicGroup: formatPercentages(ppEconomicGroup.numerator / ppEconomicGroup.denominator), - ppTechnicalGroup: formatPercentages(ppTechnicalGroup.numerator / ppTechnicalGroup.denominator), - ppGovGroup: formatPercentages(ppGovernanceGroup.numerator / ppGovernanceGroup.denominator), - treasuryWithdrawal: formatPercentages(treasuryWithdrawal.numerator / treasuryWithdrawal.denominator) - } - } - } - }; - - return ( - - ); -}; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer/ParameterChangeActionContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer/ParameterChangeActionContainer.tsx new file mode 100644 index 000000000..60cb02090 --- /dev/null +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer/ParameterChangeActionContainer.tsx @@ -0,0 +1,42 @@ +/* eslint-disable unicorn/no-array-reduce */ +import React, { useMemo } from 'react'; +import { Wallet } from '@lace/cardano'; +import { ParameterChangeAction, getParameterChangeActionViewData } from '@lace/core'; +import { useWalletStore } from '@src/stores'; + +import { useCexplorerBaseUrl } from '../../hooks'; + +interface Props { + governanceAction: Wallet.Cardano.ParameterChangeAction; + deposit: Wallet.Cardano.ProposalProcedure['deposit']; + rewardAccount: Wallet.Cardano.ProposalProcedure['rewardAccount']; + anchor: Wallet.Cardano.ProposalProcedure['anchor']; +} + +export const ParameterChangeActionContainer = ({ + governanceAction, + deposit, + rewardAccount, + anchor +}: Props): React.ReactElement => { + const { + walletUI: { cardanoCoin } + } = useWalletStore(); + + const explorerBaseUrl = useCexplorerBaseUrl(); + + const data = useMemo( + () => + getParameterChangeActionViewData({ + governanceAction, + deposit, + rewardAccount, + anchor, + cardanoCoin, + explorerBaseUrl + }), + [anchor, cardanoCoin, deposit, explorerBaseUrl, governanceAction, rewardAccount] + ); + + return ; +}; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer/index.ts b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer/index.ts new file mode 100644 index 000000000..0670b1368 --- /dev/null +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/ParameterChangeActionContainer/index.ts @@ -0,0 +1 @@ +export { ParameterChangeActionContainer } from './ParameterChangeActionContainer'; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/TreasuryWithdrawalsActionContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/TreasuryWithdrawalsActionContainer.tsx index ed81ffb33..ea857a087 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/TreasuryWithdrawalsActionContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/TreasuryWithdrawalsActionContainer.tsx @@ -1,95 +1,40 @@ import React, { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; import { Wallet } from '@lace/cardano'; -import { TreasuryWithdrawalsAction } from '@lace/core'; +import { TreasuryWithdrawalsAction, getTreasuryWithdrawalsActionViewData } from '@lace/core'; import { useWalletStore } from '@src/stores'; -import { SignTxData } from '../types'; import { useCexplorerBaseUrl } from '../hooks'; -import { depositPaidWithSymbol } from '../utils'; interface Props { - dappInfo: SignTxData['dappInfo']; governanceAction: Wallet.Cardano.TreasuryWithdrawalsAction; deposit: Wallet.Cardano.ProposalProcedure['deposit']; rewardAccount: Wallet.Cardano.ProposalProcedure['rewardAccount']; anchor: Wallet.Cardano.ProposalProcedure['anchor']; - errorMessage?: string; } export const TreasuryWithdrawalsActionContainer = ({ - dappInfo, governanceAction, deposit, rewardAccount, - anchor, - errorMessage + anchor }: Props): React.ReactElement => { - const { t } = useTranslation(); const { walletUI: { cardanoCoin } } = useWalletStore(); const explorerBaseUrl = useCexplorerBaseUrl(); - const translations = useMemo[0]['translations']>( - () => ({ - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - }, - withdrawals: { - title: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.title'), - rewardAccount: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.withdrawals.rewardAccount'), - lovelace: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.withdrawals.lovelace') - } - }), - [t] + const data = useMemo( + () => + getTreasuryWithdrawalsActionViewData({ + anchor, + cardanoCoin, + deposit, + explorerBaseUrl, + governanceAction, + rewardAccount + }), + [anchor, cardanoCoin, deposit, explorerBaseUrl, governanceAction, rewardAccount] ); - const { withdrawals } = governanceAction; - - const data: Parameters[0]['data'] = { - txDetails: { - txType: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.title'), - deposit: depositPaidWithSymbol(deposit, cardanoCoin), - rewardAccount - }, - procedure: { - anchor: { - url: anchor.url, - hash: anchor.dataHash, - txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` - } - }, - withdrawals: [...withdrawals].map((withdrawal) => ({ - rewardAccount: withdrawal.rewardAccount.toString(), - lovelace: Wallet.util.getFormattedAmount({ - amount: withdrawal.coin.toString(), - cardanoCoin - }) - })) - }; - - return ( - - ); + return ; }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/UpdateCommitteeActionContainer.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/UpdateCommitteeActionContainer.tsx index 81cad6e0f..1f3c3308f 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/UpdateCommitteeActionContainer.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/UpdateCommitteeActionContainer.tsx @@ -1,108 +1,35 @@ -import React, { useMemo } from 'react'; -import { useTranslation } from 'react-i18next'; +import React from 'react'; import { Wallet } from '@lace/cardano'; -import { UpdateCommitteeAction } from '@lace/core'; +import { UpdateCommitteeAction, getUpdateCommitteeActionViewData } from '@lace/core'; import { useWalletStore } from '@src/stores'; -import { SignTxData } from '../types'; import { useCexplorerBaseUrl } from '../hooks'; interface Props { - dappInfo: SignTxData['dappInfo']; governanceAction: Wallet.Cardano.UpdateCommittee; deposit: Wallet.Cardano.ProposalProcedure['deposit']; rewardAccount: Wallet.Cardano.ProposalProcedure['rewardAccount']; anchor: Wallet.Cardano.ProposalProcedure['anchor']; - errorMessage?: string; } export const UpdateCommitteeActionContainer = ({ - dappInfo, governanceAction, deposit, rewardAccount, - anchor, - errorMessage + anchor }: Props): React.ReactElement => { - const { t } = useTranslation(); const { walletUI: { cardanoCoin } } = useWalletStore(); const explorerBaseUrl = useCexplorerBaseUrl(); + const data = getUpdateCommitteeActionViewData({ + anchor, + cardanoCoin, + deposit, + explorerBaseUrl, + governanceAction, + rewardAccount + }); - const translations = useMemo[0]['translations']>( - () => ({ - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - }, - membersToBeAdded: { - title: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.title'), - coldCredential: { - hash: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.coldCredential.hash'), - epoch: t( - 'core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.coldCredential.epoch' - ) - } - }, - membersToBeRemoved: { - title: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeRemoved.title'), - hash: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeRemoved.hash') - } - }), - [t] - ); - - const { membersToBeAdded, membersToBeRemoved, governanceActionId } = governanceAction; - - const data: Parameters[0]['data'] = { - txDetails: { - txType: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.title'), - deposit: Wallet.util.getFormattedAmount({ - amount: deposit.toString(), - cardanoCoin - }), - rewardAccount - }, - procedure: { - anchor: { - url: anchor.url, - hash: anchor.dataHash, - txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` - } - }, - ...(governanceActionId && { - actionId: { - index: governanceActionId.actionIndex.toString(), - id: governanceActionId.id || '' - } - }), - membersToBeAdded: [...membersToBeAdded].map(({ coldCredential: { hash }, epoch }) => ({ - coldCredential: { - hash: hash.toString() - }, - epoch: epoch.toString() - })), - membersToBeRemoved: [...membersToBeRemoved].map(({ hash }) => ({ - hash: hash.toString() - })) - }; - - return ( - - ); + return ; }; diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/HardForkInitiationActionContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/HardForkInitiationActionContainer.test.tsx index ec6968d49..85abcd1b4 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/HardForkInitiationActionContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/HardForkInitiationActionContainer.test.tsx @@ -71,12 +71,6 @@ jest.mock('@lace/cardano', () => { }; }); -const dappInfo = { - name: 'dappName', - logo: 'dappLogo', - url: 'dappUrl' -}; -const errorMessage = 'errorMessage'; const deposit = BigInt('10000'); const rewardAccount = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); const anchor = { @@ -109,7 +103,7 @@ describe('Testing ProposalProceduresContainer component', () => { await act(async () => { ({ queryByTestId } = render( , { wrapper: getWrapper() @@ -120,10 +114,8 @@ describe('Testing ProposalProceduresContainer component', () => { expect(queryByTestId('HardForkInitiationAction')).toBeInTheDocument(); expect(mockHardForkInitiationAction).toHaveBeenLastCalledWith( { - dappInfo, data: { txDetails: { - txType: t('core.ProposalProcedure.governanceAction.hardForkInitiation.title'), deposit: depositPaidWithSymbol(deposit, cardanoCoinMock as Wallet.CoinId), rewardAccount }, @@ -142,33 +134,7 @@ describe('Testing ProposalProceduresContainer component', () => { index: hardForkInitiationAction.governanceActionId.actionIndex.toString(), id: hardForkInitiationAction.governanceActionId.id || '' } - }, - translations: { - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - protocolVersion: { - major: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.major'), - minor: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.minor'), - patch: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.patch') - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - } - }, - errorMessage + } }, {} ); diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/InfoActionContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/InfoActionContainer.test.tsx index f6b6eb5fc..2da559aaf 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/InfoActionContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/InfoActionContainer.test.tsx @@ -13,6 +13,7 @@ import '@testing-library/jest-dom'; import { act } from 'react-dom/test-utils'; import { InfoActionContainer } from '../InfoActionContainer'; import { getWrapper } from '../../testing.utils'; +import { mockProposalProcedure } from '@lace/core'; jest.mock('react-i18next', () => { const original = jest.requireActual('react-i18next'); @@ -41,22 +42,8 @@ jest.mock('../../hooks', () => { }; }); -const dappInfo = { - name: 'dappName', - logo: 'dappLogo', - url: 'dappUrl' -}; -const errorMessage = 'errorMessage'; -const deposit = BigInt('10000'); -const rewardAccount = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); -const anchor = { - url: 'anchorUrl', - dataHash: Wallet.Crypto.Hash32ByteBase16(Buffer.from('anchorDataHashanchorDataHashanch').toString('hex')) -}; - -const infoAction = { - __typename: Wallet.Cardano.GovernanceActionType.info_action -} as Wallet.Cardano.InfoAction; +const infoActionMock = mockProposalProcedure[Wallet.Cardano.GovernanceActionType.info_action]; +const { deposit, rewardAccount, anchor, governanceAction: infoAction } = infoActionMock; describe('Testing ProposalProceduresContainer component', () => { afterEach(() => { @@ -69,9 +56,7 @@ describe('Testing ProposalProceduresContainer component', () => { await act(async () => { ({ queryByTestId } = render( - , + , { wrapper: getWrapper() } @@ -81,11 +66,8 @@ describe('Testing ProposalProceduresContainer component', () => { expect(queryByTestId('InfoAction')).toBeInTheDocument(); expect(mockInfoAction).toHaveBeenLastCalledWith( { - dappInfo, data: { - txDetails: { - txType: t('core.ProposalProcedure.governanceAction.infoAction.title') - }, + txDetails: {}, procedure: { anchor: { url: anchor.url, @@ -93,21 +75,7 @@ describe('Testing ProposalProceduresContainer component', () => { txHashUrl: `${mockedCExpolorerBaseUrl}/${anchor.dataHash}` } } - }, - translations: { - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - } - }, - errorMessage + } }, {} ); diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/NewConstitutionActionContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/NewConstitutionActionContainer.test.tsx index 82e3f9dd4..7bc55782d 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/NewConstitutionActionContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/NewConstitutionActionContainer.test.tsx @@ -71,12 +71,6 @@ jest.mock('@lace/cardano', () => { }; }); -const dappInfo = { - name: 'dappName', - logo: 'dappLogo', - url: 'dappUrl' -}; -const errorMessage = 'errorMessage'; const deposit = BigInt('10000'); const rewardAccount = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); const anchor = { @@ -107,9 +101,7 @@ describe('Testing ProposalProceduresContainer component', () => { await act(async () => { ({ queryByTestId } = render( - , + , { wrapper: getWrapper() } @@ -119,10 +111,8 @@ describe('Testing ProposalProceduresContainer component', () => { expect(queryByTestId('NewConstitutionAction')).toBeInTheDocument(); expect(mockNewConstitutionAction).toHaveBeenLastCalledWith( { - dappInfo, data: { txDetails: { - txType: t('core.ProposalProcedure.governanceAction.newConstitutionAction.title'), deposit: depositPaidWithSymbol(deposit, cardanoCoinMock as Wallet.CoinId), rewardAccount }, @@ -144,36 +134,7 @@ describe('Testing ProposalProceduresContainer component', () => { }, scriptHash: newConstitution.constitution.scriptHash.toString() } - }, - translations: { - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - constitution: { - title: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.title'), - anchor: { - dataHash: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.anchor.dataHash'), - url: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.anchor.url') - }, - scriptHash: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.scriptHash') - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - } - }, - errorMessage + } }, {} ); diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/NoConfidenceActionContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/NoConfidenceActionContainer.test.tsx index 2327db288..d4952e070 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/NoConfidenceActionContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/NoConfidenceActionContainer.test.tsx @@ -71,12 +71,6 @@ jest.mock('@lace/cardano', () => { }; }); -const dappInfo = { - name: 'dappName', - logo: 'dappLogo', - url: 'dappUrl' -}; -const errorMessage = 'errorMessage'; const deposit = BigInt('10000'); const rewardAccount = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); const anchor = { @@ -103,9 +97,7 @@ describe('Testing ProposalProceduresContainer component', () => { await act(async () => { ({ queryByTestId } = render( - , + , { wrapper: getWrapper() } @@ -115,10 +107,8 @@ describe('Testing ProposalProceduresContainer component', () => { expect(queryByTestId('NoConfidenceAction')).toBeInTheDocument(); expect(mockNoConfidenceAction).toHaveBeenLastCalledWith( { - dappInfo, data: { txDetails: { - txType: t('core.ProposalProcedure.governanceAction.noConfidenceAction.title'), deposit: depositPaidWithSymbol(deposit, cardanoCoinMock as Wallet.CoinId), rewardAccount }, @@ -133,28 +123,7 @@ describe('Testing ProposalProceduresContainer component', () => { index: noConfidence.governanceActionId.actionIndex.toString(), id: noConfidence.governanceActionId.id || '' } - }, - translations: { - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - } - }, - errorMessage + } }, {} ); diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/ParameterChangeActionContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/ParameterChangeActionContainer.test.tsx index e694a4201..b29e801cd 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/ParameterChangeActionContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/ParameterChangeActionContainer.test.tsx @@ -73,12 +73,6 @@ jest.mock('@lace/cardano', () => { }; }); -const dappInfo = { - name: 'dappName', - logo: 'dappLogo', - url: 'dappUrl' -}; -const errorMessage = 'errorMessage'; const deposit = BigInt('10000'); const rewardAccount = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); const anchor = { @@ -189,7 +183,7 @@ describe('Testing ProposalProceduresContainer component', () => { await act(async () => { ({ queryByTestId } = render( , { wrapper: getWrapper() @@ -200,10 +194,8 @@ describe('Testing ProposalProceduresContainer component', () => { expect(queryByTestId('ParameterChangeAction')).toBeInTheDocument(); expect(mockParameterChangeAction).toHaveBeenLastCalledWith( { - dappInfo, data: { txDetails: { - txType: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.title'), deposit: depositPaidWithSymbol(deposit, cardanoCoinMock as Wallet.CoinId), rewardAccount }, @@ -307,218 +299,7 @@ describe('Testing ProposalProceduresContainer component', () => { } } } - }, - translations: { - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - }, - memory: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.memory'), - step: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.step'), - networkGroup: { - title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.title'), - maxBBSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBBSize'), - maxTxSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxTxSize'), - maxBHSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBHSize'), - maxValSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxValSize'), - maxTxExUnits: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxTxExUnits'), - maxBlockExUnits: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBlockExUnits' - ), - maxCollateralInputs: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxCollateralInputs' - ), - tooltip: { - maxBBSize: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBBSize' - ), - maxTxSize: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxTxSize' - ), - maxBHSize: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBHSize' - ), - maxValSize: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxValSize' - ), - maxTxExUnits: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxTxExUnits' - ), - maxBlockExUnits: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBlockExUnits' - ), - maxCollateralInputs: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxCollateralInputs' - ) - } - }, - economicGroup: { - title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.title'), - minFeeA: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minFeeA'), - minFeeB: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minFeeB'), - keyDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.keyDeposit'), - poolDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.poolDeposit'), - rho: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.rho'), - tau: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tau'), - minPoolCost: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minPoolCost'), - coinsPerUTxOByte: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.coinsPerUTxOByte' - ), - prices: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.prices'), - tooltip: { - minFeeA: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minFeeA'), - minFeeB: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minFeeB'), - keyDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.keyDeposit' - ), - poolDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.poolDeposit' - ), - rho: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.rho'), - tau: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.tau'), - minPoolCost: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minPoolCost' - ), - coinsPerUTxOByte: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.coinsPerUTxOByte' - ), - prices: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.prices') - } - }, - technicalGroup: { - title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.title'), - a0: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.a0'), - eMax: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.eMax'), - nOpt: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.nOpt'), - costModels: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.costModels'), - collateralPercentage: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.collateralPercentage' - ), - tooltip: { - a0: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.a0'), - eMax: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.eMax'), - nOpt: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.nOpt'), - costModels: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.costModels' - ), - collateralPercentage: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.collateralPercentage' - ) - } - }, - governanceGroup: { - title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.title'), - govActionLifetime: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.govActionLifetime' - ), - govActionDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.govActionDeposit' - ), - drepDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.drepDeposit'), - drepActivity: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.drepActivity'), - ccMinSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.ccMinSize'), - ccMaxTermLength: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.ccMaxTermLength' - ), - dRepVotingThresholds: { - title: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.title' - ), - motionNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.motionNoConfidence' - ), - committeeNormal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.committeeNormal' - ), - committeeNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.committeeNoConfidence' - ), - updateConstitution: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.updateConstitution' - ), - hardForkInitiation: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.hardForkInitiation' - ), - ppNetworkGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppNetworkGroup' - ), - ppEconomicGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppEconomicGroup' - ), - ppTechnicalGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppTechnicalGroup' - ), - ppGovernanceGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppGovernanceGroup' - ), - treasuryWithdrawal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.treasuryWithdrawal' - ) - }, - tooltip: { - govActionLifetime: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.govActionLifetime' - ), - govActionDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.govActionDeposit' - ), - drepDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.drepDeposit' - ), - drepActivity: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.drepActivity' - ), - ccMinSize: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.ccMinSize' - ), - ccMaxTermLength: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.ccMaxTermLength' - ), - dRepVotingThresholds: { - title: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.title' - ), - motionNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.motionNoConfidence' - ), - committeeNormal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.committeeNormal' - ), - committeeNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.committeeNoConfidence' - ), - updateConstitution: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.updateConstitution' - ), - hardForkInitiation: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.hardForkInitiation' - ), - ppNetworkGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppNetworkGroup' - ), - ppEconomicGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppEconomicGroup' - ), - ppTechnicalGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppTechnicalGroup' - ), - ppGovernanceGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppGovernanceGroup' - ), - treasuryWithdrawal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.treasuryWithdrawal' - ) - } - } - } - }, - errorMessage + } }, {} ); diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/TreasuryWithdrawalsActionContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/TreasuryWithdrawalsActionContainer.test.tsx index 88d93774d..0c3eae914 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/TreasuryWithdrawalsActionContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/TreasuryWithdrawalsActionContainer.test.tsx @@ -71,12 +71,6 @@ jest.mock('@lace/cardano', () => { }; }); -const dappInfo = { - name: 'dappName', - logo: 'dappLogo', - url: 'dappUrl' -}; -const errorMessage = 'errorMessage'; const deposit = BigInt('10000'); const rewardAccount = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); const anchor = { @@ -104,7 +98,7 @@ describe('Testing ProposalProceduresContainer component', () => { await act(async () => { ({ queryByTestId } = render( , { wrapper: getWrapper() @@ -115,10 +109,8 @@ describe('Testing ProposalProceduresContainer component', () => { expect(queryByTestId('TreasuryWithdrawalsAction')).toBeInTheDocument(); expect(mockTreasuryWithdrawalsAction).toHaveBeenLastCalledWith( { - dappInfo, data: { txDetails: { - txType: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.title'), deposit: depositPaidWithSymbol(deposit, cardanoCoinMock as Wallet.CoinId), rewardAccount }, @@ -136,33 +128,7 @@ describe('Testing ProposalProceduresContainer component', () => { cardanoCoin: cardanoCoinMock as Wallet.CoinId }) })) - }, - translations: { - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - }, - withdrawals: { - title: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.title'), - rewardAccount: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.withdrawals.rewardAccount'), - lovelace: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.withdrawals.lovelace') - } - }, - errorMessage + } }, {} ); diff --git a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/UpdateCommitteeActionContainer.test.tsx b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/UpdateCommitteeActionContainer.test.tsx index 39bc1874d..adc979e75 100644 --- a/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/UpdateCommitteeActionContainer.test.tsx +++ b/apps/browser-extension-wallet/src/features/dapp/components/confirm-transaction/proposal-procedures/__tests__/UpdateCommitteeActionContainer.test.tsx @@ -71,12 +71,6 @@ jest.mock('@lace/cardano', () => { }; }); -const dappInfo = { - name: 'dappName', - logo: 'dappLogo', - url: 'dappUrl' -}; -const errorMessage = 'errorMessage'; const deposit = BigInt('10000'); const rewardAccount = Wallet.Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); const anchor = { @@ -129,9 +123,7 @@ describe('Testing ProposalProceduresContainer component', () => { await act(async () => { ({ queryByTestId } = render( - , + , { wrapper: getWrapper() } @@ -141,10 +133,8 @@ describe('Testing ProposalProceduresContainer component', () => { expect(queryByTestId('UpdateCommitteeAction')).toBeInTheDocument(); expect(mockUpdateCommitteeAction).toHaveBeenLastCalledWith( { - dappInfo, data: { txDetails: { - txType: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.title'), deposit: depositPaidWithSymbol(deposit, cardanoCoinMock as Wallet.CoinId), rewardAccount }, @@ -166,43 +156,7 @@ describe('Testing ProposalProceduresContainer component', () => { epoch: epoch.toString() })), membersToBeRemoved: [...updateCommittee.membersToBeRemoved].map(({ hash }) => ({ hash: hash.toString() })) - }, - translations: { - txDetails: { - title: t('core.ProposalProcedure.txDetails.title'), - txType: t('core.ProposalProcedure.txDetails.txType'), - deposit: t('core.ProposalProcedure.txDetails.deposit'), - rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') - }, - procedure: { - title: t('core.ProposalProcedure.procedure.title'), - anchor: { - url: t('core.ProposalProcedure.procedure.anchor.url'), - hash: t('core.ProposalProcedure.procedure.anchor.hash') - } - }, - actionId: { - title: t('core.ProposalProcedure.governanceAction.actionId.title'), - index: t('core.ProposalProcedure.governanceAction.actionId.index'), - txId: t('core.ProposalProcedure.governanceAction.actionId.txId') - }, - membersToBeAdded: { - title: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.title'), - coldCredential: { - hash: t( - 'core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.coldCredential.hash' - ), - epoch: t( - 'core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.coldCredential.epoch' - ) - } - }, - membersToBeRemoved: { - title: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeRemoved.title'), - hash: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeRemoved.hash') - } - }, - errorMessage + } }, {} ); 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 be1de143b..25f77a897 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,7 +7,6 @@ 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; @@ -145,9 +144,6 @@ export const getTxType = async (tx: Wallet.Cardano.Tx): Promise - Wallet.Cardano.DRepID(Wallet.HexBlob.toTypedBech32('drep', Wallet.HexBlob(value))); - export const pubDRepKeyToHash = async ( pubDRepKeyHex: Wallet.Crypto.Ed25519PublicKeyHex ): Promise => { @@ -168,7 +164,17 @@ export const depositPaidWithSymbol = (deposit: bigint, coinId: Wallet.CoinId): s } }; -export const getDRepId = (voter: Wallet.Cardano.Voter): Wallet.Cardano.DRepID | string => - getVoterType(voter.__typename) === VoterTypeEnum.DREP - ? drepIDasBech32FromHash(voter.credential.hash) - : voter.credential.hash.toString(); +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/providers/AnalyticsProvider/analyticsTracker/events.ts b/apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/events.ts index 625a74244..1bd6eab64 100644 --- a/apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/events.ts +++ b/apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/events.ts @@ -69,7 +69,7 @@ export const postHogMultiWalletActions: PostHogMultiWalletActionsType = { WALLET_ADDED: PostHogAction.MultiWalletRestoreAdded, HD_WALLET: PostHogAction.MultiWalletRestoreHdWallet }, - hw: { + hardware: { SETUP_OPTION_CLICK: PostHogAction.MultiWalletHWClick, CONNECT_HW_VIEW: PostHogAction.MultiWalletHWConnectView, HW_POPUP_CONNECT_CLICK: PostHogAction.MultiWalletHWPopupConnectClick, diff --git a/apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/types.ts b/apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/types.ts index 6765d7f12..7f62e4e64 100644 --- a/apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/types.ts +++ b/apps/browser-extension-wallet/src/providers/AnalyticsProvider/analyticsTracker/types.ts @@ -39,7 +39,7 @@ export enum TxCreationType { } export type OnboardingFlows = 'create' | 'restore' | 'hw' | 'forgot_password' | 'onboarding'; -export type MultiWalletFlows = 'create' | 'restore' | 'hw'; +export type MultiWalletFlows = 'create' | 'restore' | 'hardware'; export type PostHogActionsKeys = | 'SETUP_OPTION_CLICK' | 'ANALYTICS_AGREE_CLICK' @@ -64,10 +64,9 @@ export type PostHogActionsKeys = | 'RECOVERY_PHRASE_PASTE_READ_MORE_CLICK' | 'WALLET_ADDED' | 'HD_WALLET'; -export type PostHogOnboardingActionsValueType = Partial>; -export type PostHogOnboardingActionsType = Record; -export type PostHogMultiWalletActionsValueType = Partial>; -export type PostHogMultiWalletActionsType = Record; +export type PostHogActions = Partial>; +export type PostHogOnboardingActionsType = Record; +export type PostHogMultiWalletActionsType = Record; export type PostHogPersonProperties = { $set: { user_tracking_type: UserTrackingType; diff --git a/apps/browser-extension-wallet/src/routes/wallet-paths.ts b/apps/browser-extension-wallet/src/routes/wallet-paths.ts index ff7e653de..292d44e7a 100644 --- a/apps/browser-extension-wallet/src/routes/wallet-paths.ts +++ b/apps/browser-extension-wallet/src/routes/wallet-paths.ts @@ -23,22 +23,9 @@ export const walletRoutePaths = { }, newWallet: { root: '/new-wallet', - create: { - root: '/new-wallet/create', - setup: '/new-wallet/create/setup', - recoveryPhrase: '/new-wallet/create/recovery-phrase' - }, - hardware: { - root: '/new-wallet/hardware', - connect: '/new-wallet/hardware/connect', - setup: '/new-wallet/hardware/setup', - create: '/new-wallet/hardware/create' - }, - restore: { - root: '/new-wallet/restore', - setup: '/new-wallet/restore/setup', - enterRecoveryPhrase: '/new-wallet/restore/enter-recovery-phrase' - } + create: '/new-wallet/create', + hardware: '/new-wallet/hardware', + restore: '/new-wallet/restore' }, sharedWallet: { root: '/add-shared-wallet' diff --git a/apps/browser-extension-wallet/src/stores/slices/activity-detail-slice.ts b/apps/browser-extension-wallet/src/stores/slices/activity-detail-slice.ts index f23a0dc73..c42a1b3d8 100644 --- a/apps/browser-extension-wallet/src/stores/slices/activity-detail-slice.ts +++ b/apps/browser-extension-wallet/src/stores/slices/activity-detail-slice.ts @@ -19,11 +19,6 @@ import { MAX_POOLS_COUNT } from '@lace/staking'; import { ActivityStatus, DelegationActivityType, TransactionActivityType } from '@lace/core'; import type { ActivityType } from '@lace/core'; import { formatDate, formatTime } from '@src/utils/format-date'; -import { - certificateTransformer, - governanceProposalsTransformer, - votingProceduresTransformer -} from '@src/views/browser-view/features/activity/helpers/common-tx-transformer'; import { createHistoricalOwnInputResolver, HistoricalOwnInputResolverArgs } from '@src/utils/own-input-resolver'; import { getCollateral } from '@cardano-sdk/core'; import { hasPhase2ValidationFailed } from '@src/utils/phase2-validation'; @@ -129,7 +124,6 @@ const buildGetActivityDetail = const { blockchainProvider: { chainHistoryProvider, stakePoolProvider, assetProvider }, inMemoryWallet: wallet, - walletUI: { cardanoCoin }, activityDetail, walletInfo, walletState @@ -250,16 +244,10 @@ const buildGetActivityDetail = metadata: txMetadata, includedUtcDate: blocks?.utcDate, includedUtcTime: blocks?.utcTime, - // TODO: store the raw data here and transform it later so we always have the raw data when needed.(LW-9570) - votingProcedures: votingProceduresTransformer(tx.body.votingProcedures), - proposalProcedures: governanceProposalsTransformer({ - cardanoCoin, - coinPrices, - fiatCurrency, - proposalProcedures: tx.body.proposalProcedures - }), - certificates: certificateTransformer(cardanoCoin, coinPrices, fiatCurrency, tx.body.certificates), - collateral: collateralInAda + collateral: collateralInAda, + votingProcedures: tx.body.votingProcedures, + proposalProcedures: tx.body.proposalProcedures, + certificates: tx.body.certificates }; if (type === DelegationActivityType.delegation && delegationInfo) { diff --git a/apps/browser-extension-wallet/src/types/activity-detail.ts b/apps/browser-extension-wallet/src/types/activity-detail.ts index 6927a1011..fcdc766e0 100644 --- a/apps/browser-extension-wallet/src/types/activity-detail.ts +++ b/apps/browser-extension-wallet/src/types/activity-detail.ts @@ -1,14 +1,11 @@ +import { Wallet } from '@lace/cardano'; import type { TransactionMetadataProps, TxOutputInput, ActivityStatus, RewardsInfo, TransactionActivityType, - ActivityType, - TxDetailsVotingProceduresTitles, - TxDetailsProposalProceduresTitles, - TxDetailsCertificateTitles, - TxDetails + ActivityType } from '@lace/core'; export enum TxDirections { @@ -38,9 +35,9 @@ type TransactionActivity = { addrOutputs?: TxOutputInput[]; metadata?: TransactionMetadataProps['metadata']; pools?: TransactionPool[]; - votingProcedures?: TxDetails[]; - proposalProcedures?: TxDetails[]; - certificates?: TxDetails[]; + votingProcedures?: Wallet.Cardano.VotingProcedures; + proposalProcedures?: Wallet.Cardano.ProposalProcedure[]; + certificates?: Wallet.Cardano.Certificate[]; }; type RewardsActivity = { diff --git a/apps/browser-extension-wallet/src/utils/tx-inspection.ts b/apps/browser-extension-wallet/src/utils/tx-inspection.ts index f36a72a0b..0cee507b9 100644 --- a/apps/browser-extension-wallet/src/utils/tx-inspection.ts +++ b/apps/browser-extension-wallet/src/utils/tx-inspection.ts @@ -19,7 +19,7 @@ import { } from '@lace/core'; import { TxDirection, TxDirections } from '@src/types'; -const { CertificateType, GovernanceActionType, Vote, VoterType, InputSource } = Wallet.Cardano; +const { CertificateType, GovernanceActionType, InputSource } = Wallet.Cardano; const hasWalletStakeAddress = ( withdrawals: Wallet.Cardano.HydratedTx['body']['withdrawals'], @@ -218,27 +218,6 @@ export const inspectTxValues = async ({ return inspectionProperties.totalOutputsValue; }; -export enum VoterTypeEnum { - CONSTITUTIONAL_COMMITTEE = 'constitutionalCommittee', - SPO = 'spo', - DREP = 'drep' -} - -export const getVoterType = (voterType: Wallet.Cardano.VoterType): VoterTypeEnum => { - switch (voterType) { - case VoterType.ccHotKeyHash: - case VoterType.ccHotScriptHash: - return VoterTypeEnum.CONSTITUTIONAL_COMMITTEE; - case VoterType.stakePoolKeyHash: - return VoterTypeEnum.SPO; - case VoterType.dRepKeyHash: - case VoterType.dRepScriptHash: - return VoterTypeEnum.DREP; - default: - return VoterTypeEnum.DREP; - } -}; - export enum CredentialType { KeyHash = 'KeyHash', ScriptHash = 'ScriptHash' @@ -254,21 +233,3 @@ export const getCredentialType = (credentialType: Wallet.Cardano.CredentialType) return CredentialType.ScriptHash; } }; - -export enum VotesEnum { - YES = 'yes', - NO = 'no', - ABSTAIN = 'abstain' -} - -export const getVote = (vote: Wallet.Cardano.Vote): VotesEnum => { - switch (vote) { - case Vote.yes: - return VotesEnum.YES; - case Vote.no: - return VotesEnum.NO; - case Vote.abstain: - default: - return VotesEnum.ABSTAIN; - } -}; diff --git a/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWallet.module.scss b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWallet.module.scss new file mode 100644 index 000000000..5fd353611 --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWallet.module.scss @@ -0,0 +1,35 @@ +@import '../../../../../../../packages/common/src/ui/styles/abstracts/mixins'; + +.card { + align-self: stretch; +} + +.titleBadge { + align-self: start; + border-radius: size_unit(2); + background: var(--primary-gradient); + display: flex; + align-items: center; + justify-content: center; + padding: 0 size_unit(1); + height: 20px; +} +.badgeCaption { + color: var(--color-white, #fff) !important; +} + +.scroll { + @include scroll-bar-style; + overflow: auto; + height: 127px; + padding: 0 4px; + color: var(--light-mode-dark-grey, var(--dark-mode-light-grey, #6f7786)); +} + +.disclaimerShort { + color: var(--light-mode-mid-grey, var(--dark-mode-light-grey, #c0c0c0)) !important; +} + +.disclaimerFullWrapper { + text-align: center; +} diff --git a/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletButton.tsx b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletButton.tsx new file mode 100644 index 000000000..ba507071a --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletButton.tsx @@ -0,0 +1,44 @@ +import { tabs } from 'webextension-polyfill'; +import { ReactComponent as AdaComponentTransparent } from '@lace/icons/dist/AdaComponentTransparent'; +import React, { useRef, useState } from 'react'; +import { Button } from '@lace/ui'; +import { TopUpWalletDialog } from './TopUpWalletDialog'; +import { useTranslation } from 'react-i18next'; +import { BANXA_LACE_URL } from './config'; +import { useAnalyticsContext } from '@providers'; +import { PostHogAction } from '@lace/common'; + +export const TopUpWalletButton = (): React.ReactElement => { + const dialogTriggerReference = useRef(null); + const [open, setOpen] = useState(false); + const { t } = useTranslation(); + const analytics = useAnalyticsContext(); + + return ( + <> + } + label={t('browserView.assets.topupWallet.buyButton.caption')} + onClick={() => { + analytics.sendEventToPostHog(PostHogAction.TokenTokensTopYourWalletBuyAdaClick); + setOpen(true); + }} + ref={dialogTriggerReference} + /> + + { + analytics.sendEventToPostHog(PostHogAction.TokenBuyAdaDisclaimerGoBackClick); + setOpen(false); + }} + open={open} + triggerRef={dialogTriggerReference} + onConfirm={() => { + analytics.sendEventToPostHog(PostHogAction.TokenBuyAdaDisclaimerContinueClick); + tabs.create({ url: BANXA_LACE_URL }); + setOpen(false); + }} + /> + + ); +}; diff --git a/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletCard.tsx b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletCard.tsx new file mode 100644 index 000000000..67c99e704 --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletCard.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { Card, Flex, Text } from '@lace/ui'; +import styles from './TopUpWallet.module.scss'; +import { useTranslation } from 'react-i18next'; +import { TopUpWalletButton } from './TopUpWalletButton'; + +export const TopUpWalletCard = (): React.ReactElement => { + const { t } = useTranslation(); + + return ( + + +
+ + {t('browserView.assets.topupWallet.card.badge')} + +
+ + {t('browserView.assets.topupWallet.card.title')} + + + + {t('browserView.assets.topupWallet.buyButton.title')} + + + + {t('browserView.assets.topupWallet.disclaimer.short')} + + +
+
+ ); +}; diff --git a/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletDialog.tsx b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletDialog.tsx new file mode 100644 index 000000000..03147305b --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/TopUpWalletDialog.tsx @@ -0,0 +1,52 @@ +import React, { useCallback } from 'react'; +import { Box, Dialog, Text, TextLink } from '@lace/ui'; +import styles from './TopUpWallet.module.scss'; +import { useTranslation } from 'react-i18next'; +import { tabs } from 'webextension-polyfill'; +import { BANXA_HOMEPAGE_URL } from './config'; + +interface TopUpWalletDialogProps { + open: boolean; + onCancel: () => void; + onConfirm: () => void; + triggerRef: React.RefObject; +} +export const TopUpWalletDialog = ({ + open, + onCancel, + onConfirm, + triggerRef +}: TopUpWalletDialogProps): React.ReactElement => { + const { t } = useTranslation(); + const handleOpenTabBanxaHomepage = useCallback(() => { + tabs.create({ url: BANXA_HOMEPAGE_URL }); + }, []); + + return ( + + {t('browserView.assets.topupWallet.modal.title')} + + + + {t('browserView.assets.topupWallet.disclaimer.full.part1')} + + + + {t('browserView.assets.topupWallet.disclaimer.full.part2')} + + + + + + + + + + ); +}; diff --git a/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/config.ts b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/config.ts new file mode 100644 index 000000000..9aeaac05d --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/config.ts @@ -0,0 +1,3 @@ +export const USE_FOOR_TOPUP = process.env.USE_FOOR_TOPUP === 'true'; +export const BANXA_LACE_URL = process.env.BANXA_LACE_URL; +export const BANXA_HOMEPAGE_URL = process.env.BANXA_HOMEPAGE_URL; diff --git a/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/index.ts b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/index.ts new file mode 100644 index 000000000..edb7054c3 --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/components/TopUpWallet/index.ts @@ -0,0 +1,2 @@ +export * from './TopUpWalletButton'; +export * from './TopUpWalletCard'; diff --git a/apps/browser-extension-wallet/src/views/browser-view/components/index.ts b/apps/browser-extension-wallet/src/views/browser-view/components/index.ts index c6d53f8f2..5fa6767bd 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/components/index.ts +++ b/apps/browser-extension-wallet/src/views/browser-view/components/index.ts @@ -8,4 +8,5 @@ export * from './SideMenu'; export * from './WarningModal'; export * from './SocialNetworks'; export * from './WalletUsedAddressesDrawer'; +export * from './TopUpWallet'; export * from './EmptySearch'; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/activity/components/TransactionDetailsProxy.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/activity/components/TransactionDetailsProxy.tsx index e5bab6689..15bdab285 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/activity/components/TransactionDetailsProxy.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/activity/components/TransactionDetailsProxy.tsx @@ -7,8 +7,8 @@ import { useAddressBookContext, withAddressBookContext } from '@src/features/add import type { TransactionActivityDetail, TxDirection } from '@src/types'; import { TxDirections } from '@src/types'; import { APP_MODE_POPUP } from '@src/utils/constants'; -import { config } from '@src/config'; import { PostHogAction } from '@providers/AnalyticsProvider/analyticsTracker'; +import { useCexplorerBaseUrl } from '@src/features/dapp/components/confirm-transaction/hooks'; import { useObservable } from '@lace/common'; import { getAllWalletsAddresses } from '@src/utils/get-all-wallets-addresses'; import { walletRepository } from '@lib/wallet-api-ui'; @@ -26,8 +26,8 @@ export const TransactionDetailsProxy = withAddressBookContext( const { inMemoryWallet, walletInfo, - environmentName, - walletUI: { cardanoCoin, appMode } + walletUI: { cardanoCoin, appMode }, + currentChain } = useWalletStore(); const isPopupView = appMode === APP_MODE_POPUP; const openExternalLink = useExternalLinkOpener(); @@ -38,16 +38,12 @@ export const TransactionDetailsProxy = withAddressBookContext( // Prepare address book data as Map const { list: addressList } = useAddressBookContext(); + const explorerBaseUrl = useCexplorerBaseUrl(); const addressToNameMap = useMemo( () => new Map(addressList?.map((item: AddressListType) => [item.address, item.name])), [addressList] ); - const { CEXPLORER_BASE_URL, CEXPLORER_URL_PATHS } = config(); - const explorerBaseUrl = useMemo( - () => `${CEXPLORER_BASE_URL[environmentName]}/${CEXPLORER_URL_PATHS.Tx}`, - [CEXPLORER_BASE_URL, CEXPLORER_URL_PATHS.Tx, environmentName] - ); const getHeaderDescription = () => { if (activityInfo.type === DelegationActivityType.delegation) return '1 token'; return ` (${activityInfo?.assetAmount})`; @@ -114,8 +110,10 @@ export const TransactionDetailsProxy = withAddressBookContext( votingProcedures={votingProcedures} certificates={certificates} handleOpenExternalHashLink={handleOpenExternalHashLink} - openExternalLink={openExternalLink} collateral={collateral} + chainNetworkId={currentChain.networkId} + cardanoCoin={cardanoCoin} + explorerBaseUrl={explorerBaseUrl} /> ); } diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/activity/helpers/common-tx-transformer.ts b/apps/browser-extension-wallet/src/views/browser-view/features/activity/helpers/common-tx-transformer.ts index d75bbe69a..e1903bfea 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/activity/helpers/common-tx-transformer.ts +++ b/apps/browser-extension-wallet/src/views/browser-view/features/activity/helpers/common-tx-transformer.ts @@ -4,29 +4,16 @@ import BigNumber from 'bignumber.js'; import { Wallet } from '@lace/cardano'; import { CurrencyInfo, TxDirections } from '@types'; -import { inspectTxValues, inspectTxType, getVoterType, getVote } from '@src/utils/tx-inspection'; +import { inspectTxValues, inspectTxType } from '@src/utils/tx-inspection'; import { formatDate, formatTime } from '@src/utils/format-date'; import { getTransactionTotalAmount } from '@src/utils/get-transaction-total-amount'; import type { TransformedActivity, TransformedTransactionActivity } from './types'; -import { - ActivityStatus, - DelegationActivityType, - TxDetails, - TxDetailsCertificateTitles, - TxDetailsVotingProceduresTitles, - TxDetailsProposalProceduresTitles, - ConwayEraCertificatesTypes, - TxDetail -} from '@lace/core'; +import { ActivityStatus, DelegationActivityType } from '@lace/core'; import capitalize from 'lodash/capitalize'; import dayjs from 'dayjs'; -import isEmpty from 'lodash/isEmpty'; -import { PriceResult } from '@hooks'; -import { formatPercentages } from '@lace/common'; -import { depositPaidWithSymbol } from '@src/features/dapp/components/confirm-transaction/utils'; import { hasPhase2ValidationFailed } from '@src/utils/phase2-validation'; -const { util, GovernanceActionType, PlutusLanguageVersion, CertificateType } = Wallet.Cardano; +const { util } = Wallet.Cardano; export interface TxTransformerInput { tx: Wallet.TxInFlight | Wallet.Cardano.HydratedTx; @@ -264,553 +251,11 @@ export const txTransformer = async ({ ]; }; -const drepMapper = (drep: Wallet.Cardano.DelegateRepresentative) => { - if (Wallet.Cardano.isDRepAlwaysAbstain(drep)) { - return 'alwaysAbstain'; - } else if (Wallet.Cardano.isDRepAlwaysNoConfidence(drep)) { - return 'alwaysNoConfidence'; - } else if (Wallet.Cardano.isDRepCredential(drep)) { - return Wallet.Cardano.DRepID(drep.hash); - } - throw new Error('incorrect drep supplied'); -}; - -export const certificateTransformer = ( - cardanoCoin: Wallet.CoinId, - coinPrices: PriceResult, - fiatCurrency: CurrencyInfo, - certificates?: Wallet.Cardano.Certificate[] -): TxDetails[] => - certificates - ?.filter((certificate) => - Object.values(ConwayEraCertificatesTypes).includes( - certificate.__typename as unknown as ConwayEraCertificatesTypes - ) - ) - .map((conwayEraCertificate) => { - const transformedCertificate: TxDetails = [ - { title: 'certificateType', details: [conwayEraCertificate.__typename] } - ]; - - if ('coldCredential' in conwayEraCertificate) { - transformedCertificate.push({ - title: 'coldCredential', - details: [conwayEraCertificate.coldCredential.hash.toString()] - }); - } - - if ('hotCredential' in conwayEraCertificate) { - transformedCertificate.push({ - title: 'hotCredential', - details: [conwayEraCertificate.hotCredential.hash.toString()] - }); - } - - if ('stakeCredential' in conwayEraCertificate) { - transformedCertificate.push({ - title: 'stakeKey', - details: [conwayEraCertificate.stakeCredential.hash.toString()] - }); - } - - if ('dRepCredential' in conwayEraCertificate) { - transformedCertificate.push({ - title: 'drepId', - details: [conwayEraCertificate.dRepCredential.hash.toString()] - }); - } - - if ('anchor' in conwayEraCertificate && conwayEraCertificate.anchor) { - transformedCertificate.push( - { - title: 'anchorHash', - details: [conwayEraCertificate.anchor.dataHash.toString()] - }, - { - title: 'anchorURL', - details: [conwayEraCertificate.anchor.url] - } - ); - } - - if ('poolId' in conwayEraCertificate) { - transformedCertificate.push({ - title: 'poolId', - details: [conwayEraCertificate.poolId.toString()] - }); - } - - if ('dRep' in conwayEraCertificate) { - transformedCertificate.push({ - title: 'drep', - details: [drepMapper(conwayEraCertificate.dRep)] - }); - } - - if ('deposit' in conwayEraCertificate) { - const depositTitle = - conwayEraCertificate.__typename === CertificateType.UnregisterDelegateRepresentative - ? 'depositReturned' - : 'depositPaid'; - transformedCertificate.push({ - title: depositTitle, - info: `${depositTitle}Info`, - details: [ - [ - Wallet.util.getFormattedAmount({ amount: conwayEraCertificate.deposit.toString(), cardanoCoin }), - `${Wallet.util.convertLovelaceToFiat({ - lovelaces: conwayEraCertificate.deposit.toString(), - fiat: coinPrices?.cardano?.price - })} ${fiatCurrency?.code}` - ] - ] - }); - } - - return transformedCertificate; - }); - -export const votingProceduresTransformer = ( - votingProcedures: Wallet.Cardano.VotingProcedures -): TxDetails[] => { - const votingProcedureDetails: TxDetails[] = []; - - votingProcedures?.forEach((procedure) => - procedure.votes.forEach((vote) => { - const detail: TxDetails = [ - { - title: 'voterType', - details: [getVoterType(procedure.voter.__typename)] - }, - { - title: 'voterCredential', - details: [procedure.voter.credential.hash.toString()] - }, - { title: 'voteTypes', details: [getVote(vote.votingProcedure.vote)] } - ]; - - if (vote.votingProcedure.anchor) { - detail.push( - { title: 'anchorURL', details: [vote.votingProcedure.anchor.url] }, - { title: 'anchorHash', details: [vote.votingProcedure.anchor.dataHash.toString()] } - ); - } - - votingProcedureDetails.push(detail.filter((el: TxDetail) => !isEmpty(el))); - }) - ); - - return votingProcedureDetails; -}; - -export const governanceProposalsTransformer = ({ - cardanoCoin, - coinPrices, - fiatCurrency, - proposalProcedures -}: { - cardanoCoin: Wallet.CoinId; - coinPrices: PriceResult; - fiatCurrency: CurrencyInfo; - proposalProcedures?: Wallet.Cardano.ProposalProcedure[]; -}): TxDetails[] => - proposalProcedures?.map((procedure) => { - const transformedProposal: TxDetails = [ - { title: 'type', details: [procedure.governanceAction.__typename] }, - { - ...(procedure.governanceAction.__typename === GovernanceActionType.parameter_change_action && { - title: 'deposit', - info: 'deposit', - details: [ - [ - Wallet.util.getFormattedAmount({ amount: procedure.deposit.toString(), cardanoCoin }), - `${Wallet.util.convertLovelaceToFiat({ - lovelaces: procedure.deposit.toString(), - fiat: coinPrices?.cardano?.price - })} ${fiatCurrency?.code}` - ] - ] - }) - }, - { title: 'rewardAccount', details: [procedure.anchor.dataHash.toString()] }, - { title: 'anchorURL', details: [procedure.anchor.url] }, - { title: 'anchorHash', details: [procedure.anchor.dataHash.toString()] } - ]; - - if ('governanceActionId' in procedure.governanceAction && procedure.governanceAction.governanceActionId) { - transformedProposal.push( - { - title: 'governanceActionID', - details: [procedure.governanceAction.governanceActionId.id.toString()] - }, - { - title: 'actionIndex', - details: [procedure.governanceAction.governanceActionId.actionIndex.toString()] - } - ); - } - - if ('withdrawals' in procedure.governanceAction) { - procedure.governanceAction.withdrawals.forEach(({ rewardAccount, coin }) => { - transformedProposal.push({ - header: 'withdrawal', - details: [ - { - title: 'withdrawalRewardAccount', - details: [rewardAccount] - }, - { - title: 'withdrawalAmount', - details: [ - Wallet.util.getFormattedAmount({ - amount: coin.toString(), - cardanoCoin - }) - ] - } - ] - }); - }); - } - - if ('constitution' in procedure.governanceAction) { - transformedProposal.push( - { - title: 'constitutionAnchorURL', - details: [procedure.governanceAction.constitution.anchor.url] - }, - { - title: 'constitutionScriptHash', - details: [procedure.governanceAction.constitution.scriptHash.toString()] - } - ); - } - - if ('membersToBeAdded' in procedure.governanceAction) { - const membersToBeAdded: TxDetail[] = []; - procedure.governanceAction.membersToBeAdded.forEach(({ coldCredential, epoch }) => { - membersToBeAdded.push( - { - title: 'coldCredentialHash', - details: [coldCredential.hash] - }, - { - title: 'epoch', - details: [epoch.toString()] - } - ); - }); - - if (membersToBeAdded.length > 0) { - transformedProposal.push({ - header: 'membersToBeAdded', - details: membersToBeAdded - }); - } - } - - if ('membersToBeRemoved' in procedure.governanceAction) { - const membersToBeRemoved: TxDetail[] = []; - procedure.governanceAction.membersToBeRemoved.forEach(({ hash }) => { - membersToBeRemoved.push({ - title: 'hash', - details: [hash.toString()] - }); - }); - - if (membersToBeRemoved.length > 0) { - transformedProposal.push({ - header: 'membersToBeRemoved', - details: membersToBeRemoved - }); - } - } - - if ('newQuorumThreshold' in procedure.governanceAction) { - transformedProposal.push({ - title: 'newQuorumThreshold', - details: [ - `${formatPercentages( - procedure.governanceAction.newQuorumThreshold.numerator / - procedure.governanceAction.newQuorumThreshold.denominator - )}%` - ] - }); - } - - if ('protocolVersion' in procedure.governanceAction) { - transformedProposal.push( - { - title: 'protocolVersionMajor', - details: [procedure.governanceAction.protocolVersion.major.toString()] - }, - { - title: 'protocolVersionMinor', - details: [procedure.governanceAction.protocolVersion.minor.toString()] - } - ); - } - - if (procedure.governanceAction.__typename === GovernanceActionType.parameter_change_action) { - const { - protocolParamUpdate: { - maxExecutionUnitsPerTransaction, - maxExecutionUnitsPerBlock, - maxBlockBodySize, - maxTxSize, - maxBlockHeaderSize, - maxValueSize, - maxCollateralInputs, - minFeeCoefficient, - minFeeConstant, - stakeKeyDeposit, - poolDeposit, - monetaryExpansion, - treasuryExpansion, - minPoolCost, - coinsPerUtxoByte, - poolInfluence, - poolRetirementEpochBound, - desiredNumberOfPools, - collateralPercentage, - costModels, - governanceActionValidityPeriod, - governanceActionDeposit, - dRepDeposit, - dRepInactivityPeriod, - minCommitteeSize, - committeeTermLimit, - dRepVotingThresholds, - prices - } - } = procedure.governanceAction; - transformedProposal.push( - { - header: 'maxTxExUnits', - details: [ - { - title: 'memory', - details: [maxExecutionUnitsPerTransaction.memory.toString()] - }, - { - title: 'step', - details: [maxExecutionUnitsPerTransaction.steps.toString()] - } - ] - }, - { - header: 'maxBlockExUnits', - details: [ - { - title: 'memory', - details: [maxExecutionUnitsPerBlock.memory.toString()] - }, - { - title: 'step', - details: [maxExecutionUnitsPerBlock.steps.toString()] - } - ] - }, - { - header: 'networkGroup', - details: [ - { - title: 'maxBBSize', - details: [maxBlockBodySize?.toString()] - }, - { - title: 'maxTxSize', - details: [maxTxSize?.toString()] - }, - { - title: 'maxBHSize', - details: [maxBlockHeaderSize?.toString()] - }, - { - title: 'maxValSize', - details: [maxValueSize?.toString()] - }, - { - title: 'maxCollateralInputs', - details: [maxCollateralInputs?.toString()] - } - ] - }, - { - header: 'economicGroup', - details: [ - { - title: 'minFeeA', - details: [minFeeCoefficient?.toString()] - }, - { - title: 'minFeeB', - details: [minFeeConstant?.toString()] - }, - { - title: 'keyDeposit', - details: [stakeKeyDeposit?.toString()] - }, - { - title: 'poolDeposit', - details: [poolDeposit?.toString()] - }, - { - title: 'rho', - details: [monetaryExpansion?.toString()] - }, - { - title: 'tau', - details: [treasuryExpansion?.toString()] - }, - { - title: 'minPoolCost', - details: [minPoolCost?.toString()] - }, - { - title: 'coinsPerUTxOByte', - details: [coinsPerUtxoByte?.toString()] - } - ] - }, - { - header: 'costModels', - details: [ - { - title: 'PlutusV1', - details: costModels.get(PlutusLanguageVersion.V1).map((model) => model.toString()) - }, - { - title: 'PlutusV2', - details: costModels.get(PlutusLanguageVersion.V2).map((model) => model.toString()) - } - ] - }, - { - header: 'technicalGroup', - details: [ - { - title: 'a0', - details: [poolInfluence?.toString()] - }, - { - title: 'eMax', - details: [poolRetirementEpochBound?.toString()] - }, - { - title: 'nOpt', - details: [desiredNumberOfPools?.toString()] - }, - { - title: 'collateralPercentage', - details: [collateralPercentage?.toString()] - } - ] - }, - { - header: 'prices', - details: [ - { - title: 'memory', - details: [prices.memory.toString()] - }, - { - title: 'step', - details: [prices.steps.toString()] - } - ] - }, - { - header: 'governanceGroup', - details: [ - { - title: 'govActionLifetime', - details: [governanceActionValidityPeriod?.toString()] - }, - { - title: 'govActionDeposit', - details: [depositPaidWithSymbol(BigInt(governanceActionDeposit), cardanoCoin)] - }, - { - title: 'drepDeposit', - details: [depositPaidWithSymbol(BigInt(dRepDeposit), cardanoCoin)] - }, - { - title: 'drepActivity', - details: [dRepInactivityPeriod?.toString()] - }, - { - title: 'ccMinSize', - details: [minCommitteeSize?.toString()] - }, - { - title: 'ccMaxTermLength', - details: [committeeTermLimit?.toString()] - } - ] - } - ); - - if (dRepVotingThresholds) { - const { - motionNoConfidence, - committeeNormal, - commiteeNoConfidence, - hardForkInitiation, - ppNetworkGroup, - ppEconomicGroup, - ppTechnicalGroup, - ppGovernanceGroup, - treasuryWithdrawal, - updateConstitution - } = dRepVotingThresholds; - transformedProposal.push({ - header: 'dRepVotingThresholds', - details: [ - { - title: 'motionNoConfidence', - details: [`${formatPercentages(motionNoConfidence.numerator / motionNoConfidence.denominator)}%`] - }, - { - title: 'committeeNormal', - details: [`${formatPercentages(committeeNormal.numerator / committeeNormal.denominator)}%`] - }, - { - title: 'committeeNoConfidence', - details: [`${formatPercentages(commiteeNoConfidence.numerator / commiteeNoConfidence.denominator)}%`] - }, - { - title: 'updateConstitution', - details: [`${formatPercentages(updateConstitution.numerator / updateConstitution.denominator)}%`] - }, - { - title: 'hardForkInitiation', - details: [`${formatPercentages(hardForkInitiation.numerator / hardForkInitiation.denominator)}%`] - }, - { - title: 'ppNetworkGroup', - details: [`${formatPercentages(ppNetworkGroup.numerator / ppNetworkGroup.denominator)}%`] - }, - { - title: 'ppEconomicGroup', - details: [`${formatPercentages(ppEconomicGroup.numerator / ppEconomicGroup.denominator)}%`] - }, - { - title: 'ppTechnicalGroup', - details: [`${formatPercentages(ppTechnicalGroup.numerator / ppTechnicalGroup.denominator)}%`] - }, - { - title: 'ppGovernanceGroup', - details: [`${formatPercentages(ppGovernanceGroup.numerator / ppGovernanceGroup.denominator)}%`] - }, - { - title: 'treasuryWithdrawal', - details: [`${formatPercentages(treasuryWithdrawal.numerator / treasuryWithdrawal.denominator)}%`] - } - ] - }); - } - } - - return transformedProposal; - }); +export interface CertificateMetadata { + certificateType: Wallet.Cardano.CertificateType; + poolId?: string; + stakeKeyHash?: string; + drepId?: string; + alwaysAbstain?: boolean; + alwaysNoConfidence?: boolean; +} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/Assets.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/Assets.tsx index c3c0098a4..4678a2714 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/Assets.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/Assets.tsx @@ -7,13 +7,13 @@ import { useBalances, useFetchCoinPrice, useRedirection } from '@hooks'; import { useWalletStore } from '@src/stores'; import { useCurrencyStore } from '@providers/currency'; import { cardanoTransformer, assetTransformer } from '@src/utils/assets-transformers'; -import { SectionLayout, Layout } from '@src/views/browser-view/components'; +import { SectionLayout, Layout, TopUpWalletCard } from '@src/views/browser-view/components'; import { useDrawer } from '@src/views/browser-view/stores'; import { DrawerContent } from '@src/views/browser-view/components/Drawer'; import { walletRoutePaths } from '@routes'; import { APP_MODE_POPUP } from '@src/utils/constants'; import { ContentLayout } from '@components/Layout'; -import { useAnalyticsContext } from '@providers'; +import { useAnalyticsContext, useAppSettingsContext } from '@providers'; import { PostHogAction } from '@providers/AnalyticsProvider/analyticsTracker'; import { isNFT } from '@src/utils/is-nft'; import { @@ -27,6 +27,10 @@ import { AssetsPortfolio } from './AssetsPortfolio/AssetsPortfolio'; import { AssetDetailsDrawer } from './AssetDetailsDrawer/AssetDetailsDrawer'; import { AssetActivityDetails } from './AssetActivityDetails/AssetActivityDetails'; import { AssetEducationalList } from './AssetEducationalList/AssetEducationalList'; +import { Flex } from '@lace/ui'; +import { USE_FOOR_TOPUP } from '@src/views/browser-view/components/TopUpWallet/config'; +import { useIsSmallerScreenWidthThan } from '@hooks/useIsSmallerScreenWidthThan'; +import { BREAKPOINT_SMALL } from '@src/styles/constants'; const LIST_CHUNK_SIZE = 12; const SEND_COIN_OUTPUT_ID = 'output1'; @@ -57,6 +61,9 @@ export const Assets = ({ topSection }: AssetsProps): React.ReactElement => { const hiddenBalancePlaceholder = getHiddenBalancePlaceholder(); const { setPickedCoin } = useCoinStateSelector(SEND_COIN_OUTPUT_ID); const { setTriggerPoint } = useAnalyticsSendFlowTriggerPoint(); + const isScreenTooSmallForSidePanel = useIsSmallerScreenWidthThan(BREAKPOINT_SMALL); + const [{ chainName }] = useAppSettingsContext(); + const isMainnet = chainName === 'Mainnet'; const [isActivityDetailsOpen, setIsActivityDetailsOpen] = useState(false); const [fullAssetList, setFullAssetList] = useState(); @@ -307,7 +314,15 @@ export const Assets = ({ topSection }: AssetsProps): React.ReactElement => { ) : ( - 0} sidePanelContent={}> + 0} + sidePanelContent={ + + {USE_FOOR_TOPUP && isMainnet && !isScreenTooSmallForSidePanel && } + + + } + > {topSection} {assetsPortfolio} {drawers} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetsPortfolio.module.scss b/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetsPortfolio.module.scss index a7a085239..8f2748a09 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetsPortfolio.module.scss +++ b/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetsPortfolio.module.scss @@ -5,7 +5,7 @@ } .portfolio { - margin-bottom: size_unit(5); + margin-bottom: size_unit(2); } .testPopupClass { @@ -19,3 +19,7 @@ margin-top: size_unit(3); } } + +.topupWalletDisclaimerShort { + color: var(--light-mode-mid-grey, var(--dark-mode-light-grey, #c0c0c0)) !important; +} \ No newline at end of file diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetsPortfolio.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetsPortfolio.tsx index 52747e13d..a036fa76a 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetsPortfolio.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/assets/components/AssetsPortfolio/AssetsPortfolio.tsx @@ -6,7 +6,7 @@ import { IRow, SendReceive } from '@lace/core'; import { SectionTitle } from '@components/Layout/SectionTitle'; import { APP_MODE_POPUP, AppMode } from '@src/utils/constants'; import { compactNumberWithUnit } from '@src/utils/format-number'; -import { PortfolioBalance } from '@src/views/browser-view/components'; +import { PortfolioBalance, TopUpWalletButton } from '@src/views/browser-view/components'; import { useCurrencyStore } from '@providers/currency'; import { useWalletStore } from '@src/stores'; import { useFetchCoinPrice } from '@hooks/useFetchCoinPrice'; @@ -19,6 +19,12 @@ import BigNumber from 'bignumber.js'; import { SendFlowTriggerPoints } from '../../../send-transaction'; import { AssetPortfolioContent } from './AssetPortfolioContent'; +import { useIsSmallerScreenWidthThan } from '@hooks/useIsSmallerScreenWidthThan'; +import { BREAKPOINT_SMALL } from '@src/styles/constants'; +import { USE_FOOR_TOPUP } from '@src/views/browser-view/components/TopUpWallet/config'; +import { Flex, Text } from '@lace/ui'; +import { Wallet } from '@lace/cardano'; + const MINUTES_UNTIL_WARNING_BANNER = 3; export interface AssetsPortfolioProps { @@ -49,13 +55,16 @@ export const AssetsPortfolio = ({ const analytics = useAnalyticsContext(); const { t } = useTranslation(); const { - walletUI: { canManageBalancesVisibility, areBalancesVisible } + walletUI: { canManageBalancesVisibility, areBalancesVisible }, + currentChain } = useWalletStore(); const { fiatCurrency } = useCurrencyStore(); const redirectToReceive = useRedirection(walletRoutePaths.receive); const redirectToSend = useRedirection<{ params: { id: string } }>(walletRoutePaths.send); + const isScreenTooSmallForSidePanel = useIsSmallerScreenWidthThan(BREAKPOINT_SMALL); const isPopupView = appMode === APP_MODE_POPUP; + const isMainnet = currentChain?.networkMagic === Wallet.Cardano.NetworkMagics.Mainnet; const portfolioBalanceAsBigNumber = useMemo(() => new BigNumber(portfolioTotalBalance), [portfolioTotalBalance]); const isPortfolioBalanceLoading = useMemo( @@ -117,6 +126,19 @@ export const AssetsPortfolio = ({ }} /> )} + {!isPopupView && isScreenTooSmallForSidePanel && USE_FOOR_TOPUP && isMainnet && ( + + + {t('browserView.assets.topupWallet.buyButton.title')} + + + + + + {t('browserView.assets.topupWallet.disclaimer.short')} + + + )} { { void analytics.sendEventToPostHog(postHogMultiWalletActions.create.SETUP_OPTION_CLICK); - history.push(walletRoutePaths.newWallet.create.root); + history.push(walletRoutePaths.newWallet.create); }} onHardwareWalletRequest={() => { - void analytics.sendEventToPostHog(postHogMultiWalletActions.hw.SETUP_OPTION_CLICK); - history.push(walletRoutePaths.newWallet.hardware.root); + void analytics.sendEventToPostHog(postHogMultiWalletActions.hardware.SETUP_OPTION_CLICK); + history.push(walletRoutePaths.newWallet.hardware); }} onRestoreWalletRequest={() => { void analytics.sendEventToPostHog(postHogMultiWalletActions.restore.SETUP_OPTION_CLICK); - history.push(walletRoutePaths.newWallet.restore.root); + history.push(walletRoutePaths.newWallet.restore); }} translations={walletSetupOptionsStepTranslations} /> diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/MultiWallet.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/MultiWallet.tsx index c9624f115..84cfa2340 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/MultiWallet.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/MultiWallet.tsx @@ -1,97 +1,43 @@ /* eslint-disable unicorn/no-null */ -/* eslint-disable react/no-multi-comp */ -import React from 'react'; -import { Route, Switch, useHistory, useRouteMatch } from 'react-router-dom'; -import { Modal } from 'antd'; - -import styles from './MultiWallet.module.scss'; - -import { Home } from './components/Home'; - -import { - WalletSetupConfirmationDialogProvider, - WalletSetupFlow, - WalletSetupFlowProvider, - useWalletSetupConfirmationDialog -} from '@lace/core'; -import { CreateWallet } from './create-wallet'; -import { HardwareWallet } from './hardware-wallet'; -import { RestoreWallet } from './restore-wallet'; -import { walletRoutePaths } from '@routes'; -import { Subject } from 'rxjs'; -import { Wallet } from '@lace/cardano'; import { NavigationButton } from '@lace/common'; +import { WalletSetupConfirmationDialogProvider, WalletSetupFlow, WalletSetupFlowProvider } from '@lace/core'; import { useBackgroundPage } from '@providers/BackgroundPageProvider'; +import { walletRoutePaths } from '@routes'; +import { Modal } from 'antd'; +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import styles from './MultiWallet.module.scss'; +import { WalletOnboardingFlows } from './WalletOnboardingFlows'; +import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; +import { Home } from './Home'; -const { newWallet } = walletRoutePaths; - -interface Props { - shouldShowConfirmationDialog$: Subject; -} - -export const SetupHardwareWallet = ({ shouldShowConfirmationDialog$ }: Props): JSX.Element => ( - -); - -export const SetupCreateWallet = ({ shouldShowConfirmationDialog$ }: Props): JSX.Element => ( - -); - -export const SetupRestoreWallet = ({ shouldShowConfirmationDialog$ }: Props): JSX.Element => ( - -); - -const Component = (): JSX.Element => { - const { path } = useRouteMatch(); +export const MultiWallet = (): JSX.Element => { const history = useHistory(); const { page, setBackgroundPage } = useBackgroundPage(); - const { isDialogOpen, withConfirmationDialog, shouldShowDialog$ } = useWalletSetupConfirmationDialog(); - const closeWalletCreation = withConfirmationDialog(() => { - setBackgroundPage(); - history.push(page); - }); return ( - -
- -
- - } - /> - } - /> - } - /> - - -
+ + {({ isDialogOpen, withConfirmationDialog, shouldShowDialog$ }) => ( + +
+ { + setBackgroundPage(); + history.push(page); + })} + /> +
+ } + setFormDirty={(dirty) => shouldShowDialog$.next(dirty)} + urlPath={walletRoutePaths.newWallet} + /> +
+ )} +
); }; - -export const MultiWallet = (): JSX.Element => ( - - - -); diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/WalletOnboardingFlows.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/WalletOnboardingFlows.tsx new file mode 100644 index 000000000..1d59b417a --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/WalletOnboardingFlows.tsx @@ -0,0 +1,56 @@ +import { useKeyboardShortcut } from '@lace/common'; +import { Redirect, Route, Switch, useRouteMatch } from 'react-router-dom'; +import { CreateWallet } from './create-wallet'; +import { HardwareWallet } from './hardware-wallet'; +import { RestoreWallet } from './restore-wallet'; +import React, { ReactNode, VFC } from 'react'; +import { Flows, WalletOnboardingPostHogActions, SetFormDirty } from './types'; +import { WalletOnboardingProvider } from './walletOnboardingContext'; + +type WalletOnboardingProps = { + aliasEventRequired?: boolean; + flowsEnabled?: boolean; + forgotPasswordFlowActive?: boolean; + postHogActions: WalletOnboardingPostHogActions; + renderHome: () => ReactNode; + setFormDirty?: SetFormDirty; + urlPath: Record; +}; + +export const WalletOnboardingFlows: VFC = ({ + aliasEventRequired = false, + flowsEnabled = true, + forgotPasswordFlowActive = false, + postHogActions, + renderHome, + setFormDirty = () => void 0, + urlPath +}) => { + useKeyboardShortcut(['Enter'], () => { + const nextBnt: HTMLButtonElement = document.querySelector('[data-testid="wallet-setup-step-btn-next"]'); + const confirmGoBack: HTMLButtonElement = document.querySelector('[data-testid="delete-address-modal-confirm"]'); + + if (confirmGoBack) { + confirmGoBack.click(); + } else if (nextBnt && !nextBnt.getAttribute('disabled')) { + nextBnt.click(); + } + }); + + const { path } = useRouteMatch(); + return ( + + + + {flowsEnabled && ( + <> + + + + + )} + {!flowsEnabled && } + + + ); +}; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/CreateWallet.test.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/CreateWallet.test.tsx index 9df07590c..7d9e87081 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/CreateWallet.test.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/CreateWallet.test.tsx @@ -1,5 +1,5 @@ /* eslint-disable import/imports-first */ -import { BehaviorSubject, firstValueFrom, of } from 'rxjs'; +import { of } from 'rxjs'; jest.doMock('@hooks/useWalletManager', () => ({ useWalletManager: jest.fn().mockReturnValue({ createWallet: jest.fn().mockResolvedValue({ @@ -18,24 +18,24 @@ jest.doMock('@hooks/useWalletManager', () => ({ import React from 'react'; import '@testing-library/jest-dom'; import { fireEvent, render, screen } from '@testing-library/react'; -import { MemoryRouter } from 'react-router-dom'; -import { Providers } from './types'; -import { walletRoutePaths } from '@routes'; import { DEFAULT_MNEMONIC_LENGTH, createAssetsRoute, fillMnemonic, getNextButton, - mnemonicWords, setupStep, - getBackButton + getBackButton, + mnemonicWords } from '../tests/utils'; import { StoreProvider } from '@src/stores'; import { APP_MODE_BROWSER } from '@src/utils/constants'; import { AppSettingsProvider, DatabaseProvider } from '@providers'; import { UseWalletManager } from '@hooks/useWalletManager'; -import { AnalyticsTracker } from '@providers/AnalyticsProvider/analyticsTracker'; -import { CreateWallet } from './CreateWallet'; +import { AnalyticsTracker, postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; +import { MemoryRouter, Router } from 'react-router-dom'; +import { WalletOnboardingFlows } from '../WalletOnboardingFlows'; +import { walletRoutePaths } from '@routes'; +import { createMemoryHistory } from 'history'; jest.mock('@providers/AnalyticsProvider', () => ({ useAnalyticsContext: jest @@ -47,6 +47,23 @@ jest.mock('@providers/AnalyticsProvider', () => ({ }) })); +jest.mock('@lace/cardano', () => { + const actual = jest.requireActual('@lace/cardano'); + return { + ...actual, + Wallet: { + ...actual.Wallet, + KeyManagement: { + ...actual.Wallet.KeyManagement, + util: { + ...actual.Wallet.KeyManagement.util, + generateMnemonicWords: () => mnemonicWords + } + } + } + }; +}); + const recoveryPhraseStep = async () => { let nextButton = getNextButton(); fireEvent.click(nextButton); @@ -57,66 +74,60 @@ const recoveryPhraseStep = async () => { }; describe('Multi Wallet Setup/Create Wallet', () => { - let providers = {} as { - createWallet: jest.Mock; - generateMnemonicWords: jest.Mock; - shouldShowConfirmationDialog$: BehaviorSubject; - }; - - beforeEach(() => { - providers = { - createWallet: jest.fn(), - generateMnemonicWords: jest.fn(), - shouldShowConfirmationDialog$: new BehaviorSubject(false) - }; - }); - test('setting up a new hot wallet', async () => { - providers.generateMnemonicWords.mockReturnValue(mnemonicWords); - providers.createWallet.mockResolvedValue(void 0); - + const history = createMemoryHistory(); render( - - + + <>} + /> {createAssetsRoute()} - + ); + history.push(walletRoutePaths.newWallet.create); await recoveryPhraseStep(); await setupStep(); }); - test('should emit correct value for shouldShowDialog', async () => { - providers.generateMnemonicWords.mockReturnValue(mnemonicWords); - + test('should properly mark for dirty', async () => { + let formDirty = false; render( - - - {createAssetsRoute()} + + <>} + setFormDirty={(dirty) => { + formDirty = dirty; + }} + /> ); - expect(await firstValueFrom(providers.shouldShowConfirmationDialog$)).toBe(false); + expect(formDirty).toBe(false); const nextButton = getNextButton(); fireEvent.click(nextButton); - expect(await firstValueFrom(providers.shouldShowConfirmationDialog$)).toBe(true); + expect(formDirty).toBe(true); const backButton = getBackButton(); fireEvent.click(backButton); fireEvent.click(screen.queryByTestId('delete-address-modal-confirm')); - expect(await firstValueFrom(providers.shouldShowConfirmationDialog$)).toBe(false); + expect(formDirty).toBe(false); }); }); diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/CreateWallet.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/CreateWallet.tsx index 8c44fc65b..430aac323 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/CreateWallet.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/CreateWallet.tsx @@ -1,25 +1,18 @@ import React from 'react'; -import { Redirect, Route, Switch } from 'react-router-dom'; import { Setup } from './steps/Setup'; import { NewRecoveryPhrase } from './steps/NewRecoveryPhrase'; import { CreateWalletProvider } from './context'; -import { walletRoutePaths } from '@routes'; -import { Providers } from './types'; +import { WalletCreateStep } from './types'; -const { - newWallet: { create } -} = walletRoutePaths; - -interface Props { - providers: Providers; -} - -export const CreateWallet = ({ providers }: Props): JSX.Element => ( - - - - - - +export const CreateWallet = (): JSX.Element => ( + + {({ step }) => ( + <> + {(step === WalletCreateStep.RecoveryPhraseWriteDown || step === WalletCreateStep.RecoveryPhraseInput) && ( + + )} + {step === WalletCreateStep.Setup && } + + )} ); diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/context.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/context.tsx index 094488095..7314e0da4 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/context.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/context.tsx @@ -1,24 +1,14 @@ import { CreateWalletParams } from '@hooks'; +import { Wallet } from '@lace/cardano'; import { walletRoutePaths } from '@routes'; -import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; -import React, { createContext, useContext, useState } from 'react'; +import React, { createContext, useContext, useMemo, useState } from 'react'; import { useHistory } from 'react-router'; import { useHotWalletCreation } from '../useHotWalletCreation'; -import { Providers } from './types'; - -interface Props { - children: React.ReactNode; - providers: Providers; -} +import { useWalletOnboarding } from '../walletOnboardingContext'; +import { WalletCreateStep } from './types'; type OnNameAndPasswordChange = (state: { name: string; password: string }) => void; -export enum WalletCreateStep { - RecoveryPhraseWriteDown = 'RecoveryPhraseWriteDown', - RecoveryPhraseInput = 'RecoveryPhraseInput', - Setup = 'Setup' -} - interface State { back: () => void; createWalletData: CreateWalletParams; @@ -27,6 +17,10 @@ interface State { step: WalletCreateStep; } +interface Props { + children: (state: State) => React.ReactNode; +} + // eslint-disable-next-line unicorn/no-null const CreateWalletContext = createContext(null); @@ -36,8 +30,9 @@ export const useCreateWallet = (): State => { return state; }; -export const CreateWalletProvider = ({ children, providers }: Props): React.ReactElement => { +export const CreateWalletProvider = ({ children }: Props): React.ReactElement => { const history = useHistory(); + const { postHogActions, setFormDirty } = useWalletOnboarding(); const { clearSecrets, createWallet: createHotWallet, @@ -45,27 +40,23 @@ export const CreateWalletProvider = ({ children, providers }: Props): React.Reac sendPostWalletAddAnalytics, setCreateWalletData } = useHotWalletCreation({ - initialMnemonic: providers.generateMnemonicWords() + initialMnemonic: Wallet.KeyManagement.util.generateMnemonicWords() }); const [step, setStep] = useState(WalletCreateStep.RecoveryPhraseWriteDown); const generateMnemonic = () => { - setCreateWalletData((prevState) => ({ ...prevState, mnemonic: providers.generateMnemonicWords() })); + setCreateWalletData((prevState) => ({ ...prevState, mnemonic: Wallet.KeyManagement.util.generateMnemonicWords() })); }; const onNameAndPasswordChange: OnNameAndPasswordChange = ({ name, password }) => { setCreateWalletData((prevState) => ({ ...prevState, name, password })); }; - const setFormDirty = (dirty: boolean) => { - providers.shouldShowConfirmationDialog$.next(dirty); - }; - const finalizeWalletCreation = async () => { const wallet = await createHotWallet(); await sendPostWalletAddAnalytics({ extendedAccountPublicKey: wallet.source.account.extendedAccountPublicKey, - walletAddedPostHogAction: postHogMultiWalletActions.create.WALLET_ADDED + walletAddedPostHogAction: postHogActions.create.WALLET_ADDED }); clearSecrets(); }; @@ -79,7 +70,6 @@ export const CreateWalletProvider = ({ children, providers }: Props): React.Reac } case WalletCreateStep.RecoveryPhraseInput: { setStep(WalletCreateStep.Setup); - history.push(walletRoutePaths.newWallet.create.setup); break; } case WalletCreateStep.Setup: { @@ -104,23 +94,21 @@ export const CreateWalletProvider = ({ children, providers }: Props): React.Reac } case WalletCreateStep.Setup: { setStep(WalletCreateStep.RecoveryPhraseInput); - history.push(walletRoutePaths.newWallet.create.recoveryPhrase); break; } } }; - return ( - - {children} - + const state = useMemo( + () => ({ + back, + createWalletData, + next, + onNameAndPasswordChange, + step + }), + [back, createWalletData, next, onNameAndPasswordChange, step] ); + + return {children(state)}; }; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/steps/NewRecoveryPhrase.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/steps/NewRecoveryPhrase.tsx index c7284a227..8d6b44326 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/steps/NewRecoveryPhrase.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/steps/NewRecoveryPhrase.tsx @@ -1,14 +1,15 @@ import { MnemonicVideoPopupContent, WalletSetupMnemonicStage, WalletSetupMnemonicStepRevamp } from '@lace/core'; -import React, { useState } from 'react'; +import React, { useState, VFC } from 'react'; import { Trans, useTranslation } from 'react-i18next'; import { wordlists } from 'bip39'; import { WarningModal } from '@src/views/browser-view/components'; -import { useCreateWallet, WalletCreateStep } from '../context'; +import { useCreateWallet } from '../context'; +import { WalletCreateStep } from '../types'; import { useAnalyticsContext } from '@providers/AnalyticsProvider'; -import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; import { toast } from '@lace/common'; import Copy from '@assets/icons/copy.component.svg'; import Paste from '@assets/icons/paste.component.svg'; +import { useWalletOnboarding } from '../../walletOnboardingContext'; const wordList = wordlists.english; const COPY_PASTE_TOOLTIP_URL = `${process.env.FAQ_URL}?question=best-practices-for-using-the-copy-to-clipboard-paste-from-clipboard-recovery-phrase-features`; @@ -20,16 +21,17 @@ const getMnemonicStage = (step: WalletCreateStep): WalletSetupMnemonicStage => { throw new Error('Invalid wallet crate step'); }; -export const NewRecoveryPhrase = (): JSX.Element => { +export const NewRecoveryPhrase: VFC = () => { const { t } = useTranslation(); + const { postHogActions } = useWalletOnboarding(); const { back, createWalletData, next, step } = useCreateWallet(); const analytics = useAnalyticsContext(); const [isResetMnemonicModalOpen, setIsResetMnemonicModalOpen] = useState(false); const handleReadMoreOnClick = () => { step === WalletCreateStep.RecoveryPhraseWriteDown - ? analytics.sendEventToPostHog(postHogMultiWalletActions.create.RECOVERY_PHRASE_COPY_READ_MORE_CLICK) - : analytics.sendEventToPostHog(postHogMultiWalletActions.create.RECOVERY_PHRASE_PASTE_READ_MORE_CLICK); + ? analytics.sendEventToPostHog(postHogActions.create.RECOVERY_PHRASE_COPY_READ_MORE_CLICK) + : analytics.sendEventToPostHog(postHogActions.create.RECOVERY_PHRASE_PASTE_READ_MORE_CLICK); }; const walletSetupMnemonicStepTranslations = { @@ -74,14 +76,14 @@ export const NewRecoveryPhrase = (): JSX.Element => { onStageChange={(nextStage) => { if (nextStage === 'input') { void next(); - void analytics.sendEventToPostHog(postHogMultiWalletActions.create.SAVE_RECOVERY_PHRASE_NEXT_CLICK); + void analytics.sendEventToPostHog(postHogActions.create.SAVE_RECOVERY_PHRASE_NEXT_CLICK); } else { setIsResetMnemonicModalOpen(true); } }} onBack={back} onNext={() => { - void analytics.sendEventToPostHog(postHogMultiWalletActions.create.ENTER_RECOVERY_PHRASE_NEXT_CLICK); + void analytics.sendEventToPostHog(postHogActions.create.ENTER_RECOVERY_PHRASE_NEXT_CLICK); void next(); }} renderVideoPopupContent={({ onClose }) => ( @@ -90,9 +92,7 @@ export const NewRecoveryPhrase = (): JSX.Element => { videoSrc={process.env.YOUTUBE_RECOVERY_PHRASE_VIDEO_URL} onClose={() => { onClose(); - void analytics.sendEventToPostHog( - postHogMultiWalletActions.create.RECOVERY_PHRASE_INTRO_VIDEO_GOTIT_CLICK - ); + void analytics.sendEventToPostHog(postHogActions.create.RECOVERY_PHRASE_INTRO_VIDEO_GOTIT_CLICK); }} /> )} @@ -100,10 +100,10 @@ export const NewRecoveryPhrase = (): JSX.Element => { suggestionList={wordList} passphraseInfoLink={`${process.env.FAQ_URL}?question=what-happens-if-i-lose-my-recovery-phrase`} onWatchVideoClick={() => - void analytics.sendEventToPostHog(postHogMultiWalletActions.create.RECOVERY_PHRASE_INTRO_WATCH_VIDEO_CLICK) + void analytics.sendEventToPostHog(postHogActions.create.RECOVERY_PHRASE_INTRO_WATCH_VIDEO_CLICK) } onCopyToClipboard={() => { - void analytics.sendEventToPostHog(postHogMultiWalletActions.create.RECOVERY_PHRASE_COPY_TO_CLIPBOARD_CLICK); + void analytics.sendEventToPostHog(postHogActions.create.RECOVERY_PHRASE_COPY_TO_CLIPBOARD_CLICK); toast.notify({ duration: twoSecondsToastDuration, text: t('core.walletSetupMnemonicStepRevamp.recoveryPhraseCopied'), @@ -111,9 +111,7 @@ export const NewRecoveryPhrase = (): JSX.Element => { }); }} onPasteFromClipboard={() => { - void analytics.sendEventToPostHog( - postHogMultiWalletActions.create.RECOVERY_PHRASE_PASTE_FROM_CLIPBOARD_CLICK - ); + void analytics.sendEventToPostHog(postHogActions.create.RECOVERY_PHRASE_PASTE_FROM_CLIPBOARD_CLICK); toast.notify({ duration: twoSecondsToastDuration, text: t('core.walletSetupMnemonicStepRevamp.recoveryPhrasePasted'), diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/steps/Setup.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/steps/Setup.tsx index 5cb226259..ec7b52581 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/steps/Setup.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/steps/Setup.tsx @@ -3,9 +3,10 @@ import { useAnalyticsContext } from '@providers'; import React from 'react'; import { useTranslation } from 'react-i18next'; import { useCreateWallet } from '../context'; -import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; +import { useWalletOnboarding } from '../../walletOnboardingContext'; export const Setup = (): JSX.Element => { + const { postHogActions } = useWalletOnboarding(); const { back, createWalletData, next, onNameAndPasswordChange } = useCreateWallet(); const analytics = useAnalyticsContext(); const { t } = useTranslation(); @@ -25,7 +26,7 @@ export const Setup = (): JSX.Element => { }; const onNext = async () => { - void analytics.sendEventToPostHog(postHogMultiWalletActions.create.ENTER_WALLET); + void analytics.sendEventToPostHog(postHogActions.create.ENTER_WALLET); await next(); }; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/types.ts b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/types.ts index 879801355..25b1c83dd 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/types.ts +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/create-wallet/types.ts @@ -1,12 +1,12 @@ import { Subject } from 'rxjs'; -export interface Data { - mnemonic: string[]; - name: string; - password: string; -} - export interface Providers { generateMnemonicWords: () => string[]; shouldShowConfirmationDialog$: Subject; } + +export enum WalletCreateStep { + RecoveryPhraseWriteDown = 'RecoveryPhraseWriteDown', + RecoveryPhraseInput = 'RecoveryPhraseInput', + Setup = 'Setup' +} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/ErrorDialog.module.scss b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/ErrorDialog.module.scss new file mode 100644 index 000000000..fa2d298a0 --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/ErrorDialog.module.scss @@ -0,0 +1,38 @@ +@import '../../../../../../../../packages/common/src/ui/styles/theme'; +@import '../../../../../../../../packages/common/src/ui/styles/abstracts/typography'; + +.errorDialog { + :global(.ant-modal-content) { + background: var(--color-white, var(--dark-mode-light-black)); + box-shadow: var(--shadow-setup-box); + border-radius: size_unit(4); + } + :global(.ant-modal-body) { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: size_unit(5) !important; + } +} + +.title { + font-size: var(--subHeading) !important; + font-weight: 700 !important; + line-height: size_unit(4) !important; + color: var(--text-color-primary) !important; + margin-bottom: 0 !important; +} + +.description { + font-size: var(--bodyLarge) !important; + font-weight: 500 !important; + line-height: size_unit(3) !important; + color: var(--text-color-secondary) !important; + margin-top: size_unit(3) !important; + text-align: center; +} + +.retryButton { + margin-top: size_unit(3) !important; +} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/ErrorDialog.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/ErrorDialog.tsx index a5c129aa1..489e82189 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/ErrorDialog.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/ErrorDialog.tsx @@ -1,11 +1,20 @@ -import { makeErrorDialog } from '@views/browser/features/wallet-setup/components/HardwareWalletFlow'; +import { Button } from '@lace/common'; +import { TranslationKey } from '@lace/translation'; +import { Modal, Typography } from 'antd'; +import React from 'react'; +import { useTranslation } from 'react-i18next'; +import styles from './ErrorDialog.module.scss'; + import { ErrorDialogCode } from './types'; const commonErrorDialogTranslationKeys = { title: 'browserView.onboarding.errorDialog.title' as const, confirm: 'browserView.onboarding.errorDialog.cta' as const }; -export const ErrorDialog = makeErrorDialog({ + +type TranslationKeys = Record<'title' | 'description' | 'confirm', TranslationKey>; + +const translationsMap: Record = { [ErrorDialogCode.DeviceDisconnected]: { ...commonErrorDialogTranslationKeys, description: 'browserView.onboarding.errorDialog.messageDeviceDisconnected' @@ -18,4 +27,36 @@ export const ErrorDialog = makeErrorDialog({ ...commonErrorDialogTranslationKeys, description: 'browserView.onboarding.errorDialog.messageGeneric' } -}); +}; + +const { Title, Text } = Typography; + +type ErrorDialogProps = { + onRetry: () => void; + errorCode?: ErrorDialogCode; +}; + +export const ErrorDialog = ({ onRetry, errorCode }: ErrorDialogProps): React.ReactElement => { + const { t } = useTranslation(); + const errorTranslationKeys = translationsMap[errorCode]; + + return ( + + + {t(errorTranslationKeys.title)} + + {t(errorTranslationKeys.description)} + + + ); +}; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/HardwareWallet.test.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/HardwareWallet.test.tsx index 22ff5c845..6d230ca60 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/HardwareWallet.test.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/HardwareWallet.test.tsx @@ -1,5 +1,5 @@ /* eslint-disable import/imports-first */ -import { of, Subject } from 'rxjs'; +import { of } from 'rxjs'; jest.mock('@lib/wallet-api-ui', () => ({ walletRepository: { @@ -15,13 +15,12 @@ import React from 'react'; import '@testing-library/jest-dom'; import { createMemoryHistory } from 'history'; import { act, fireEvent, render, waitFor, screen } from '@testing-library/react'; -import { HardwareWallet } from './HardwareWallet'; +import { WalletOnboardingFlows } from '../WalletOnboardingFlows'; import { MemoryRouter, Router } from 'react-router-dom'; -import { Providers } from './types'; import { walletRoutePaths } from '@routes'; import { Wallet } from '@lace/cardano'; import { createAssetsRoute, getNextButton } from '../tests/utils'; -import { AnalyticsTracker } from '@providers/AnalyticsProvider/analyticsTracker'; +import { AnalyticsTracker, postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; import { APP_MODE_BROWSER } from '@utils/constants'; import { StoreProvider } from '@src/stores'; import { AppSettingsProvider, DatabaseProvider } from '@providers'; @@ -32,7 +31,7 @@ jest.mock('@providers/AnalyticsProvider', () => ({ useAnalyticsContext: jest .fn, []>() .mockReturnValue({ - sendEventToPostHog: jest.fn().mockReturnValue(''), + sendEventToPostHog: jest.fn(), sendMergeEvent: jest.fn(), sendAliasEvent: jest.fn() }) @@ -69,10 +68,6 @@ const createStep = async () => { }; describe('Multi Wallet Setup/Hardware Wallet', () => { - let providers = {} as { - shouldShowConfirmationDialog$: Subject; - }; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error const originalUsbDeviceClass = globalThis.USBDevice; @@ -83,10 +78,6 @@ describe('Multi Wallet Setup/Hardware Wallet', () => { let deviceObject: any; beforeEach(() => { - providers = { - shouldShowConfirmationDialog$: new Subject() - }; - // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-expect-error globalThis.USBDevice = class USBDevice {}; @@ -142,7 +133,11 @@ describe('Multi Wallet Setup/Hardware Wallet', () => { - + <>} + /> {createAssetsRoute()} @@ -151,7 +146,7 @@ describe('Multi Wallet Setup/Hardware Wallet', () => { ); act(() => { - history.push(walletRoutePaths.newWallet.hardware.connect); + history.push(walletRoutePaths.newWallet.hardware); }); await connectHardwareWalletStep(); @@ -164,8 +159,12 @@ describe('Multi Wallet Setup/Hardware Wallet', () => { - - + + <>} + /> diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/HardwareWallet.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/HardwareWallet.tsx index 24b1620fb..d23d38d12 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/HardwareWallet.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/HardwareWallet.tsx @@ -1,38 +1,25 @@ -import { walletRoutePaths } from '@routes'; import { StartOverDialog } from '@views/browser/features/wallet-setup/components/StartOverDialog'; import React from 'react'; -import { Redirect, Route, Switch } from 'react-router-dom'; import { HardwareWalletProvider } from './context'; import { ErrorDialog } from './ErrorDialog'; import { Connect } from './steps/Connect'; import { Setup } from './steps/Setup'; import { Create } from './steps/Create'; -import { Providers } from './types'; +import { WalletConnectStep } from './types'; -const { - newWallet: { hardware } -} = walletRoutePaths; - -interface Props { - providers: Providers; -} - -export const HardwareWallet = ({ providers }: Props): JSX.Element => ( - - {({ errorDialogCode, onErrorDialogRetry, isStartOverDialogVisible, onStartOverDialogAction }) => ( +export const HardwareWallet = (): JSX.Element => ( + + {({ errorDialogCode, onErrorDialogRetry, isStartOverDialogVisible, onStartOverDialogAction, step }) => ( <> - {!!errorDialogCode && } + {!!errorDialogCode && } onStartOverDialogAction(true)} onClose={() => onStartOverDialogAction(false)} /> - - - - - - + {step === WalletConnectStep.Connect && } + {step === WalletConnectStep.Setup && } + {step === WalletConnectStep.Create && } )} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/context.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/context.tsx index 9784472f7..0210377e3 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/context.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/context.tsx @@ -3,14 +3,14 @@ import { Wallet } from '@lace/cardano'; import React, { createContext, useCallback, useContext, useEffect, useMemo, useState } from 'react'; import { useHistory } from 'react-router-dom'; import { useWalletManager } from '@hooks'; -import { Providers, ErrorDialogCode } from './types'; +import { ErrorDialogCode, WalletConnectStep } from './types'; import { WalletConflictError, WalletType } from '@cardano-sdk/web-extension'; import { walletRoutePaths } from '@routes'; import { useWrapWithTimeout } from './useWrapWithTimeout'; -import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; import { useAnalyticsContext } from '@providers'; import { getWalletAccountsQtyString } from '@utils/get-wallet-count-string'; import { firstValueFrom } from 'rxjs'; +import { useWalletOnboarding } from '../walletOnboardingContext'; type WalletData = { accountIndex: number; @@ -20,19 +20,19 @@ type OnNameAndAccountChange = ({ accountIndex, name }: WalletData) => void; interface State { back: () => void; - next: () => void; connect: (usbDevice: USBDevice) => Promise; - onNameAndAccountChange: OnNameAndAccountChange; createWallet: () => Promise; errorDialogCode: ErrorDialogCode; - onErrorDialogRetry: () => void; isStartOverDialogVisible: boolean; + next: () => void; + onErrorDialogRetry: () => void; + onNameAndAccountChange: OnNameAndAccountChange; onStartOverDialogAction: (confirmed: boolean) => void; + step: WalletConnectStep; } interface HardwareWalletProviderProps { children: (state: State) => React.ReactNode; - providers: Providers; } // eslint-disable-next-line unicorn/no-null @@ -44,15 +44,11 @@ export const useHardwareWallet = (): State => { return state; }; -enum WalletConnectStep { - Connect = 'Connect', - Setup = 'Setup', - Create = 'Create' -} - -export const HardwareWalletProvider = ({ children, providers }: HardwareWalletProviderProps): React.ReactElement => { +export const HardwareWalletProvider = ({ children }: HardwareWalletProviderProps): React.ReactElement => { const analytics = useAnalyticsContext(); const history = useHistory(); + const { aliasEventRequired } = useWalletOnboarding(); + const { postHogActions, setFormDirty } = useWalletOnboarding(); const { connectHardwareWalletRevamped, createHardwareWalletRevamped, saveHardwareWallet, walletRepository } = useWalletManager(); const [step, setStep] = useState(WalletConnectStep.Connect); @@ -93,13 +89,11 @@ export const HardwareWalletProvider = ({ children, providers }: HardwareWalletPr switch (step) { case WalletConnectStep.Connect: { setStep(WalletConnectStep.Setup); - history.push(walletRoutePaths.newWallet.hardware.setup); - providers.shouldShowConfirmationDialog$.next(true); + setFormDirty(true); break; } case WalletConnectStep.Setup: { setStep(WalletConnectStep.Create); - history.push(walletRoutePaths.newWallet.hardware.create); break; } case WalletConnectStep.Create: { @@ -108,7 +102,7 @@ export const HardwareWalletProvider = ({ children, providers }: HardwareWalletPr break; } } - }, [closeConnection, history, providers.shouldShowConfirmationDialog$, step]); + }, [closeConnection, history, step]); const back = useCallback(() => { switch (step) { @@ -121,22 +115,20 @@ export const HardwareWalletProvider = ({ children, providers }: HardwareWalletPr if (isStartOverDialogVisible) { closeConnection(); setStep(WalletConnectStep.Connect); - history.push(walletRoutePaths.newWallet.hardware.connect); - providers.shouldShowConfirmationDialog$.next(false); + setFormDirty(false); } else { setIsStartOverDialogVisible(true); } break; } } - }, [closeConnection, history, isStartOverDialogVisible, providers.shouldShowConfirmationDialog$, step]); + }, [closeConnection, history, isStartOverDialogVisible, setFormDirty, step]); const cleanupConnectionState = useCallback(() => { setConnection(undefined); setStep(WalletConnectStep.Connect); - history.push(walletRoutePaths.newWallet.hardware.connect); closeConnection(); - }, [closeConnection, history]); + }, [closeConnection]); const onErrorDialogRetry = useCallback(() => { setErrorDialogCode(undefined); @@ -199,7 +191,7 @@ export const HardwareWalletProvider = ({ children, providers }: HardwareWalletPr } const deviceSpec = await Wallet.getDeviceSpec(connection); - await analytics.sendEventToPostHog(postHogMultiWalletActions.hw.WALLET_ADDED, { + await analytics.sendEventToPostHog(postHogActions.hardware.WALLET_ADDED, { /* eslint-disable camelcase */ $set_once: { initial_hardware_wallet_model: deviceSpec.model, @@ -212,39 +204,45 @@ export const HardwareWalletProvider = ({ children, providers }: HardwareWalletPr await analytics.sendMergeEvent(cardanoWallet.source.account.extendedAccountPublicKey); await saveHardwareWallet(cardanoWallet); - await analytics.sendAliasEvent(); + if (aliasEventRequired) { + await analytics.sendAliasEvent(); + } }, [ + aliasEventRequired, analytics, closeConnection, connection, createHardwareWalletRevamped, + postHogActions.hardware.WALLET_ADDED, saveHardwareWallet, walletData, walletRepository ]); - const value = useMemo( + const value = useMemo( () => ({ back, - next, connect, createWallet, - onNameAndAccountChange, errorDialogCode, - onErrorDialogRetry, isStartOverDialogVisible, - onStartOverDialogAction + next, + onErrorDialogRetry, + onNameAndAccountChange, + onStartOverDialogAction, + step }), [ back, - next, connect, createWallet, - onNameAndAccountChange, errorDialogCode, - onErrorDialogRetry, isStartOverDialogVisible, - onStartOverDialogAction + next, + onErrorDialogRetry, + onNameAndAccountChange, + onStartOverDialogAction, + step ] ); diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/steps/Connect.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/steps/Connect.tsx index d9cfd847a..5b21e0bf8 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/steps/Connect.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/steps/Connect.tsx @@ -6,9 +6,9 @@ import { TFunction } from 'i18next'; import React, { useCallback, useEffect, useState, VFC } from 'react'; import { useTranslation } from 'react-i18next'; import { useAnalyticsContext } from '@providers'; -import { postHogOnboardingActions } from '@providers/AnalyticsProvider/analyticsTracker'; import { useHardwareWallet } from '../context'; import { isTimeoutError } from '../useWrapWithTimeout'; +import { useWalletOnboarding } from '../../walletOnboardingContext'; export const isTrezorHWSupported = (): boolean => process.env.USE_TREZOR_HW === 'true'; @@ -64,6 +64,7 @@ enum DiscoveryState { export const Connect: VFC = () => { const { t } = useTranslation(); + const { postHogActions } = useWalletOnboarding(); const { back, connect, next } = useHardwareWallet(); const [discoveryState, setDiscoveryState] = useState(DiscoveryState.Requested); const [connectionError, setConnectionError] = useState(null); @@ -74,8 +75,8 @@ export const Connect: VFC = () => { const onRetry = useCallback(() => { setDiscoveryState(DiscoveryState.Requested); setConnectionError(null); - void analytics.sendEventToPostHog(postHogOnboardingActions.hw.CONNECT_HW_TRY_AGAIN_CLICK); - }, [analytics]); + void analytics.sendEventToPostHog(postHogActions.hardware.CONNECT_HW_TRY_AGAIN_CLICK); + }, [analytics, postHogActions.hardware.CONNECT_HW_TRY_AGAIN_CLICK]); useEffect(() => { (async () => { @@ -83,9 +84,9 @@ export const Connect: VFC = () => { setDiscoveryState(DiscoveryState.Running); try { - void analytics.sendEventToPostHog(postHogOnboardingActions.hw.CONNECT_HW_VIEW); + void analytics.sendEventToPostHog(postHogActions.hardware.CONNECT_HW_VIEW); const usbDevice = await requestHardwareWalletConnection(); - void analytics.sendEventToPostHog(postHogOnboardingActions.hw.HW_POPUP_CONNECT_CLICK); + void analytics.sendEventToPostHog(postHogActions.hardware.HW_POPUP_CONNECT_CLICK); await connect(usbDevice); setDiscoveryState(DiscoveryState.Idle); next(); @@ -95,7 +96,7 @@ export const Connect: VFC = () => { setConnectionError(parseConnectionError(error)); } })(); - }, [connect, discoveryState, analytics, next]); + }, [connect, discoveryState, analytics, next, postHogActions.hardware]); return ( { const analytics = useAnalyticsContext(); + const { postHogActions } = useWalletOnboarding(); const { back, next, onNameAndAccountChange } = useHardwareWallet(); return ( { - void analytics.sendEventToPostHog(postHogOnboardingActions.hw.ENTER_WALLET); + void analytics.sendEventToPostHog(postHogActions.hardware.ENTER_WALLET); onNameAndAccountChange({ accountIndex, name }); next(); }} onSelectedAccountChange={() => { - void analytics.sendEventToPostHog(postHogOnboardingActions.hw.SETUP_HW_ACCOUNT_NO_CLICK); + void analytics.sendEventToPostHog(postHogActions.hardware.SETUP_HW_ACCOUNT_NO_CLICK); }} /> ); diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/types.ts b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/types.ts index 55039d70a..df29a153e 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/types.ts +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/hardware-wallet/types.ts @@ -9,3 +9,9 @@ export enum ErrorDialogCode { PublicKeyExportRejected = 'PublicKeyExportRejected', Generic = 'Generic' } + +export enum WalletConnectStep { + Connect = 'Connect', + Setup = 'Setup', + Create = 'Create' +} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/RestoreWallet.test.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/RestoreWallet.test.tsx index dadd4ce97..f0cdf2053 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/RestoreWallet.test.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/RestoreWallet.test.tsx @@ -1,5 +1,5 @@ /* eslint-disable import/imports-first */ -import { Subject, of } from 'rxjs'; +import { of } from 'rxjs'; jest.doMock('@hooks/useWalletManager', () => ({ useWalletManager: jest.fn().mockReturnValue({ createWallet: jest.fn().mockResolvedValue({ @@ -19,16 +19,15 @@ jest.doMock('@hooks/useWalletManager', () => ({ import React from 'react'; import '@testing-library/jest-dom'; import { fireEvent, render, screen } from '@testing-library/react'; -import { MemoryRouter } from 'react-router-dom'; -import { Providers } from './types'; -import { walletRoutePaths } from '@routes'; import { DEFAULT_MNEMONIC_LENGTH, createAssetsRoute, fillMnemonic, setupStep, getNextButton } from '../tests/utils'; import { StoreProvider } from '@src/stores'; import { APP_MODE_BROWSER } from '@src/utils/constants'; import { AppSettingsProvider, DatabaseProvider } from '@providers'; import { UseWalletManager } from '@hooks/useWalletManager'; -import { AnalyticsTracker } from '@providers/AnalyticsProvider/analyticsTracker'; -import { RestoreWallet } from './RestoreWallet'; +import { AnalyticsTracker, postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; +import { MemoryRouter } from 'react-router-dom'; +import { walletRoutePaths } from '@routes'; +import { WalletOnboardingFlows } from '@views/browser/features/multi-wallet/WalletOnboardingFlows'; jest.mock('@providers/AnalyticsProvider', () => ({ useAnalyticsContext: jest.fn, []>().mockReturnValue({ @@ -45,27 +44,17 @@ const recoveryPhraseStep = async () => { }; describe('Multi Wallet Setup/Restore Wallet', () => { - let providers = {} as { - createWallet: jest.Mock; - shouldShowConfirmationDialog$: Subject; - }; - - beforeEach(() => { - providers = { - createWallet: jest.fn(), - shouldShowConfirmationDialog$: new Subject() - }; - }); - test('setting up a new hot wallet', async () => { - providers.createWallet.mockResolvedValue(void 0); - render( - - + + <>} + /> {createAssetsRoute()} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/RestoreWallet.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/RestoreWallet.tsx index 4e73b3355..9c374fdf7 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/RestoreWallet.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/RestoreWallet.tsx @@ -1,25 +1,16 @@ import React from 'react'; -import { Redirect, Route, Switch } from 'react-router-dom'; import { Setup } from './steps/Setup'; import { RestoreRecoveryPhrase } from './steps/RestoreRecoveryPhrase'; import { RestoreWalletProvider } from './context'; -import { walletRoutePaths } from '@routes'; -import { Providers } from './types'; +import { WalletRestoreStep } from './types'; -const { - newWallet: { restore } -} = walletRoutePaths; - -interface Props { - providers: Providers; -} - -export const RestoreWallet = ({ providers }: Props): JSX.Element => ( - - - - - - +export const RestoreWallet = (): JSX.Element => ( + + {({ step }) => ( + <> + {step === WalletRestoreStep.RecoveryPhrase && } + {step === WalletRestoreStep.Setup && } + + )} ); diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/context.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/context.tsx index 962d5f0a5..b0add4783 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/context.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/context.tsx @@ -1,5 +1,5 @@ -import React, { createContext, useCallback, useContext, useState } from 'react'; -import { Providers } from './types'; +import React, { createContext, useCallback, useContext, useMemo, useState } from 'react'; +import { WalletRestoreStep } from './types'; import { CreateWalletParams } from '@hooks'; import { Wallet } from '@lace/cardano'; import { useHistory } from 'react-router'; @@ -9,30 +9,26 @@ import { isScriptAddress } from '@cardano-sdk/wallet'; import { walletRoutePaths } from '@routes'; import { useHotWalletCreation } from '../useHotWalletCreation'; import { RecoveryPhraseLength } from '@lace/core'; -import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; - -interface Props { - children: React.ReactNode; - providers: Providers; -} +import { useWalletOnboarding } from '../walletOnboardingContext'; +import { deleteFromLocalStorage } from '@utils/local-storage'; type OnNameAndPasswordChange = (state: { name: string; password: string }) => void; type OnRecoveryPhraseLengthChange = (length: RecoveryPhraseLength) => void; -enum WalletRestoreStep { - RecoveryPhrase = 'RecoveryPhrase', - Setup = 'Setup' -} - interface State { back: () => void; - finalizeWalletRestoration: () => Promise; createWalletData: CreateWalletParams; + finalizeWalletRestoration: () => Promise; next: () => Promise; onNameAndPasswordChange: OnNameAndPasswordChange; - setMnemonic: (mnemonic: string[]) => void; onRecoveryPhraseLengthChange: OnRecoveryPhraseLengthChange; + setMnemonic: (mnemonic: string[]) => void; + step: WalletRestoreStep; +} + +interface Props { + children: (state: State) => React.ReactNode; } // eslint-disable-next-line unicorn/no-null @@ -46,9 +42,10 @@ export const useRestoreWallet = (): State => { const initialMnemonicLength: RecoveryPhraseLength = 24; -export const RestoreWalletProvider = ({ children, providers }: Props): React.ReactElement => { +export const RestoreWalletProvider = ({ children }: Props): React.ReactElement => { const history = useHistory(); const analytics = useAnalyticsContext(); + const { forgotPasswordFlowActive, postHogActions, setFormDirty } = useWalletOnboarding(); const [step, setStep] = useState(WalletRestoreStep.RecoveryPhrase); const { clearSecrets, createWallet, createWalletData, sendPostWalletAddAnalytics, setCreateWalletData } = useHotWalletCreation({ @@ -58,10 +55,10 @@ export const RestoreWalletProvider = ({ children, providers }: Props): React.Rea const setMnemonic = useCallback( (mnemonic: string[]) => { const mnemonicNotEmpty = mnemonic.some((m) => m); - providers.shouldShowConfirmationDialog$.next(mnemonicNotEmpty); + setFormDirty(mnemonicNotEmpty); setCreateWalletData((prevState) => ({ ...prevState, mnemonic })); }, - [providers.shouldShowConfirmationDialog$, setCreateWalletData] + [setCreateWalletData, setFormDirty] ); const onRecoveryPhraseLengthChange: OnRecoveryPhraseLengthChange = (length) => { @@ -76,7 +73,7 @@ export const RestoreWalletProvider = ({ children, providers }: Props): React.Rea const addresses = await firstValueFrom(wallet.addresses$.pipe(filter((a) => a.length > 0))); const hdWalletDiscovered = addresses.some((addr) => !isScriptAddress(addr) && addr.index > 0); if (hdWalletDiscovered) { - await analytics.sendEventToPostHog(postHogMultiWalletActions.restore.HD_WALLET); + await analytics.sendEventToPostHog(postHogActions.restore.HD_WALLET); } }; @@ -84,9 +81,12 @@ export const RestoreWalletProvider = ({ children, providers }: Props): React.Rea const wallet = await createWallet(); void sendPostWalletAddAnalytics({ extendedAccountPublicKey: wallet.source.account.extendedAccountPublicKey, - walletAddedPostHogAction: postHogMultiWalletActions.restore.WALLET_ADDED + walletAddedPostHogAction: postHogActions.restore.WALLET_ADDED }); void sendHdWalletAnalyticEvent(wallet); + if (forgotPasswordFlowActive) { + deleteFromLocalStorage('isForgotPasswordFlow'); + } clearSecrets(); }; @@ -94,7 +94,6 @@ export const RestoreWalletProvider = ({ children, providers }: Props): React.Rea switch (step) { case WalletRestoreStep.RecoveryPhrase: setStep(WalletRestoreStep.Setup); - history.push(walletRoutePaths.newWallet.restore.setup); break; case WalletRestoreStep.Setup: history.push(walletRoutePaths.assets); @@ -105,29 +104,37 @@ export const RestoreWalletProvider = ({ children, providers }: Props): React.Rea const back = () => { switch (step) { case WalletRestoreStep.RecoveryPhrase: - providers.shouldShowConfirmationDialog$.next(false); + setFormDirty(false); history.push(walletRoutePaths.newWallet.root); break; case WalletRestoreStep.Setup: setStep(WalletRestoreStep.RecoveryPhrase); - history.push(walletRoutePaths.newWallet.restore.enterRecoveryPhrase); break; } }; - return ( - - {children} - + const state = useMemo( + () => ({ + back, + createWalletData, + finalizeWalletRestoration, + next, + onNameAndPasswordChange, + onRecoveryPhraseLengthChange, + setMnemonic, + step + }), + [ + back, + createWalletData, + finalizeWalletRestoration, + next, + onNameAndPasswordChange, + onRecoveryPhraseLengthChange, + setMnemonic, + step + ] ); + + return {children(state)}; }; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/steps/RestoreRecoveryPhrase.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/steps/RestoreRecoveryPhrase.tsx index 046330b0f..ba620091b 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/steps/RestoreRecoveryPhrase.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/steps/RestoreRecoveryPhrase.tsx @@ -5,7 +5,7 @@ import { wordlists } from 'bip39'; import { Wallet } from '@lace/cardano'; import { useRestoreWallet } from '../context'; import { useAnalyticsContext } from '@providers/AnalyticsProvider'; -import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; +import { useWalletOnboarding } from '../../walletOnboardingContext'; const wordList = wordlists.english; const DEFAULT_MNEMONIC_LENGTH = 24; @@ -13,6 +13,7 @@ const COPY_PASTE_TOOLTIP_URL = `${process.env.FAQ_URL}?question=best-practices-f export const RestoreRecoveryPhrase = (): JSX.Element => { const { t } = useTranslation(); + const { forgotPasswordFlowActive, postHogActions } = useWalletOnboarding(); const { back, createWalletData, next, setMnemonic, onRecoveryPhraseLengthChange } = useRestoreWallet(); const analytics = useAnalyticsContext(); const isValidMnemonic = useMemo( @@ -24,7 +25,7 @@ export const RestoreRecoveryPhrase = (): JSX.Element => { ); const handleReadMoreOnClick = () => { - void analytics.sendEventToPostHog(postHogMultiWalletActions.restore.RECOVERY_PHRASE_PASTE_READ_MORE_CLICK); + void analytics.sendEventToPostHog(postHogActions.restore.RECOVERY_PHRASE_PASTE_READ_MORE_CLICK); }; const walletSetupMnemonicStepTranslations = { @@ -51,7 +52,7 @@ export const RestoreRecoveryPhrase = (): JSX.Element => { const handleMnemonicVerification = (event: Readonly>) => { event.preventDefault(); - void analytics.sendEventToPostHog(postHogMultiWalletActions.restore.ENTER_RECOVERY_PHRASE_NEXT_CLICK); + void analytics.sendEventToPostHog(postHogActions.restore.ENTER_RECOVERY_PHRASE_NEXT_CLICK); void next(); }; @@ -59,7 +60,7 @@ export const RestoreRecoveryPhrase = (): JSX.Element => { { defaultMnemonicLength={DEFAULT_MNEMONIC_LENGTH} onSetMnemonicLength={onRecoveryPhraseLengthChange} onPasteFromClipboard={() => - analytics.sendEventToPostHog(postHogMultiWalletActions.restore.RECOVERY_PHRASE_PASTE_FROM_CLIPBOARD_CLICK) + analytics.sendEventToPostHog(postHogActions.restore.RECOVERY_PHRASE_PASTE_FROM_CLIPBOARD_CLICK) } /> ); diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/steps/Setup.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/steps/Setup.tsx index 7000a5488..5d07407db 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/steps/Setup.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/steps/Setup.tsx @@ -6,16 +6,21 @@ import { toast } from '@lace/common'; import { useAnalyticsContext } from '@providers'; import { WalletConflictError } from '@cardano-sdk/web-extension'; import { TOAST_DEFAULT_DURATION } from '@hooks/useActionExecution'; -import { postHogMultiWalletActions } from '@providers/AnalyticsProvider/analyticsTracker'; +import { useWalletOnboarding } from '../../walletOnboardingContext'; export const Setup = (): JSX.Element => { const { back, createWalletData, finalizeWalletRestoration, next, onNameAndPasswordChange } = useRestoreWallet(); const analytics = useAnalyticsContext(); + const { forgotPasswordFlowActive, postHogActions } = useWalletOnboarding(); const { t } = useTranslation(); const translations = { - title: t('core.walletNameAndPasswordSetupStep.title'), - description: t('core.walletNameAndPasswordSetupStep.description'), + title: forgotPasswordFlowActive + ? t('core.walletNameAndPasswordSetupStep.forgotPasswordTitle') + : t('core.walletNameAndPasswordSetupStep.title'), + description: forgotPasswordFlowActive + ? t('core.walletNameAndPasswordSetupStep.forgotPasswordSubtitle') + : t('core.walletNameAndPasswordSetupStep.description'), nameInputLabel: t('core.walletNameAndPasswordSetupStep.nameInputLabel'), nameMaxLength: t('core.walletNameAndPasswordSetupStep.nameMaxLength'), passwordInputLabel: t('core.walletNameAndPasswordSetupStep.passwordInputLabel'), @@ -28,7 +33,7 @@ export const Setup = (): JSX.Element => { }; const onNext = async () => { - void analytics.sendEventToPostHog(postHogMultiWalletActions.restore.ENTER_WALLET); + void analytics.sendEventToPostHog(postHogActions.restore.ENTER_WALLET); try { await finalizeWalletRestoration(); diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/types.ts b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/types.ts index 504179b58..2194e183e 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/types.ts +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/restore-wallet/types.ts @@ -1,12 +1,10 @@ import { Subject } from 'rxjs'; -export interface Data { - mnemonic: string[]; - length: number; - name: string; - password: string; -} - export interface Providers { shouldShowConfirmationDialog$: Subject; } + +export enum WalletRestoreStep { + RecoveryPhrase = 'RecoveryPhrase', + Setup = 'Setup' +} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/types.ts b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/types.ts new file mode 100644 index 000000000..794ba19bc --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/types.ts @@ -0,0 +1,7 @@ +import { PostHogActions } from '@providers/AnalyticsProvider/analyticsTracker'; + +export type SetFormDirty = (dirty: boolean) => void; + +export type Flows = 'create' | 'restore' | 'hardware'; + +export type WalletOnboardingPostHogActions = Record; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/useHotWalletCreation.ts b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/useHotWalletCreation.ts index e43b5ea1f..991c89650 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/useHotWalletCreation.ts +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/useHotWalletCreation.ts @@ -5,6 +5,7 @@ import { useAnalyticsContext } from '@providers'; import { getWalletAccountsQtyString } from '@utils/get-wallet-count-string'; import { useEffect, useState } from 'react'; import { firstValueFrom } from 'rxjs'; +import { useWalletOnboarding } from './walletOnboardingContext'; type UseSoftwareWalletCreationParams = { initialMnemonic: string[]; @@ -19,6 +20,7 @@ type SendPostWalletAddAnalyticsParams = { export const useHotWalletCreation = ({ initialMnemonic }: UseSoftwareWalletCreationParams) => { const analytics = useAnalyticsContext(); const walletManager = useWalletManager(); + const { aliasEventRequired } = useWalletOnboarding(); const [createWalletData, setCreateWalletData] = useState({ mnemonic: initialMnemonic, name: '', @@ -45,6 +47,9 @@ export const useHotWalletCreation = ({ initialMnemonic }: UseSoftwareWalletCreat $set: { wallet_accounts_quantity: await getWalletAccountsQtyString(walletManager.walletRepository) } }); await analytics.sendMergeEvent(extendedAccountPublicKey); + if (aliasEventRequired) { + await analytics.sendAliasEvent(); + } }; const clearSecrets = () => { diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/walletOnboardingContext.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/walletOnboardingContext.tsx new file mode 100644 index 000000000..b721410f4 --- /dev/null +++ b/apps/browser-extension-wallet/src/views/browser-view/features/multi-wallet/walletOnboardingContext.tsx @@ -0,0 +1,20 @@ +import { createContext, useContext } from 'react'; +import { SetFormDirty, WalletOnboardingPostHogActions } from './types'; + +type ContextValue = { + aliasEventRequired: boolean; + forgotPasswordFlowActive: boolean; + postHogActions: WalletOnboardingPostHogActions; + setFormDirty: SetFormDirty; +}; + +// eslint-disable-next-line unicorn/no-null +const context = createContext(null); + +export const useWalletOnboarding = (): ContextValue => { + const state = useContext(context); + if (state === null) throw new Error('WalletOnboardingContext not defined'); + return state; +}; + +export const WalletOnboardingProvider = context.Provider; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.tsx index 3afd9e288..4c504eddb 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/send-transaction/components/Form/Form.tsx @@ -54,8 +54,6 @@ export const Form = ({ const { setNewOutput } = useOutputs(); - const isEmptyAssets = !assetBalances?.size; - const handleAddRow = () => { const nextBundleId = getNextBundleCoinId(spendableCoin?.toString(), assetBalances, tokensUsed, assets, cardanoCoin); setNewOutput(nextBundleId); @@ -131,7 +129,7 @@ export const Form = ({ className={styles.actionBtn} onClick={handleAddRow} data-testid="add-bundle-button" - disabled={bundleDisabled || isEmptyAssets} + disabled={bundleDisabled} > {t('browserView.transaction.send.advanced.output')} diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetup.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetup.tsx index 4c6bff0ef..7b9137378 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetup.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetup.tsx @@ -1,118 +1,55 @@ -import { WalletSetupSteps, WalletSetupFlowProvider, WalletSetupFlow } from '@lace/core'; -import { useAnalyticsContext } from '@providers/AnalyticsProvider'; import { walletRoutePaths } from '@routes/wallet-paths'; -import { ILocalStorage } from '@src/types'; -import { deleteFromLocalStorage, getValueFromLocalStorage } from '@src/utils/local-storage'; -import React, { useCallback, useEffect } from 'react'; -import { Redirect, Route, Switch, useHistory, useRouteMatch } from 'react-router-dom'; -import { HardwareWalletFlow } from './HardwareWalletFlow'; +import React, { useEffect } from 'react'; +import { deleteFromLocalStorage, getValueFromLocalStorage } from '@utils/local-storage'; import { Portal } from './Portal'; -import { SendOnboardingAnalyticsEvent, SetupType } from '../types'; -import { WalletSetupWizard } from './WalletSetupWizard'; import { getUserIdService } from '@providers/AnalyticsProvider/getUserIdService'; import { ENHANCED_ANALYTICS_OPT_IN_STATUS_LS_KEY } from '@providers/AnalyticsProvider/config'; import { WalletSetupMainPage } from './WalletSetupMainPage'; import { useLocalStorage } from '@hooks'; -import { EnhancedAnalyticsOptInStatus } from '@providers/AnalyticsProvider/analyticsTracker'; -const userIdService = getUserIdService(); +import { EnhancedAnalyticsOptInStatus, postHogOnboardingActions } from '@providers/AnalyticsProvider/analyticsTracker'; +import { WalletOnboardingFlows } from '@views/browser/features/multi-wallet/WalletOnboardingFlows'; +import { WalletSetupLayout } from '@views/browser/components'; -// This initial step is needed for configure the step that we want to snapshot -export interface WalletSetupProps { - initialStep?: WalletSetupSteps; -} - -export const WalletSetup = ({ initialStep = WalletSetupSteps.Mnemonic }: WalletSetupProps): React.ReactElement => { - const history = useHistory(); - const { path } = useRouteMatch(); - const analytics = useAnalyticsContext(); - const isForgotPasswordFlow = getValueFromLocalStorage('isForgotPasswordFlow'); +export const WalletSetup = (): React.ReactElement => { + const isForgotPasswordFlow = getValueFromLocalStorage('isForgotPasswordFlow'); const [enhancedAnalyticsStatus] = useLocalStorage( ENHANCED_ANALYTICS_OPT_IN_STATUS_LS_KEY, EnhancedAnalyticsOptInStatus.NotSet ); useEffect(() => { - const handleEnterKeyPress = (event: KeyboardEvent) => { - if (event.code === 'Enter') { - const nextBnt: HTMLButtonElement = document.querySelector('[data-testid="wallet-setup-step-btn-next"]'); - const confirmGoBack: HTMLButtonElement = document.querySelector('[data-testid="delete-address-modal-confirm"]'); - - if (confirmGoBack) { - confirmGoBack.click(); - } else if (nextBnt && !nextBnt.getAttribute('disabled')) { - nextBnt.click(); - } - } - }; - document.addEventListener('keydown', handleEnterKeyPress); - return () => { - document.removeEventListener('keydown', handleEnterKeyPress); - }; - }, []); + if (!isForgotPasswordFlow) return () => void 0; - const clearUserIdService = useCallback(async () => { - await userIdService.resetToDefaultValues(); - }, []); - // reset values in user ID service if the background storage and local storage are manually removed - useEffect(() => { - void clearUserIdService(); - }, [clearUserIdService]); + // reset values in user ID service if the background storage and local storage are manually removed + void getUserIdService().resetToDefaultValues(); - const clearWallet = useCallback(() => { - deleteFromLocalStorage('wallet'); - deleteFromLocalStorage(ENHANCED_ANALYTICS_OPT_IN_STATUS_LS_KEY); - deleteFromLocalStorage('isForgotPasswordFlow'); - }, []); - - // delete "forgot_password" related data if user leaves the flow before completing - useEffect(() => { - if (isForgotPasswordFlow) { - window.addEventListener('beforeunload', clearWallet); - } + // delete "forgot_password" related data if user leaves the flow before completing + const clearWallet = () => { + deleteFromLocalStorage('wallet'); + deleteFromLocalStorage(ENHANCED_ANALYTICS_OPT_IN_STATUS_LS_KEY); + deleteFromLocalStorage('isForgotPasswordFlow'); + }; + window.addEventListener('beforeunload', clearWallet); return () => { window.removeEventListener('beforeunload', clearWallet); }; - }, [clearWallet, isForgotPasswordFlow]); - - const cancelWalletFlow = () => history.push(walletRoutePaths.setup.home); - - const sendAnalyticsHandler: SendOnboardingAnalyticsEvent = async (postHogAction, postHogProperties) => - await analytics.sendEventToPostHog(postHogAction, postHogProperties); + }, [isForgotPasswordFlow]); return ( - - - - - - - {enhancedAnalyticsStatus === EnhancedAnalyticsOptInStatus.NotSet ? ( - - ) : ( - <> - - - - - - - - - - - )} - - - + + + } + urlPath={walletRoutePaths.setup} + /> + + ); }; diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetupMainPage.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetupMainPage.tsx index c8e0684b6..60a66fb24 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetupMainPage.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetupMainPage.tsx @@ -1,6 +1,6 @@ import React, { ReactElement, useState } from 'react'; import { Trans, useTranslation } from 'react-i18next'; -import { WalletSetupLayout, WarningModal } from '@views/browser/components'; +import { WarningModal } from '@views/browser/components'; import { AnalyticsConfirmationBanner, WalletAnalyticsInfo, WalletSetupOptionsStepRevamp } from '@lace/core'; import styles from '@views/browser/features/wallet-setup/components/WalletSetup.module.scss'; import { walletRoutePaths } from '@routes'; @@ -116,14 +116,12 @@ export const WalletSetupMainPage = (): ReactElement => { return ( <> - - - + diff --git a/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetupWizard.tsx b/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetupWizard.tsx index 806f31fcf..d29788d28 100644 --- a/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetupWizard.tsx +++ b/apps/browser-extension-wallet/src/views/browser-view/features/wallet-setup/components/WalletSetupWizard.tsx @@ -75,7 +75,6 @@ export const WalletSetupWizard = ({ const { t } = useTranslation(); const { updateEnteredAtTime } = useTimeSpentOnPage(); - useEffect(() => { updateEnteredAtTime(); }, [currentStep, updateEnteredAtTime]); diff --git a/packages/cardano/src/wallet/util/drep.ts b/packages/cardano/src/wallet/util/drep.ts new file mode 100644 index 000000000..72ec374f1 --- /dev/null +++ b/packages/cardano/src/wallet/util/drep.ts @@ -0,0 +1,7 @@ +import { Hash28ByteBase16 } from '@cardano-sdk/crypto'; +import { Cardano } from '@cardano-sdk/core'; +import { HexBlob } from '@cardano-sdk/util'; + +export const drepIDasBech32FromHash = (value: Hash28ByteBase16): Cardano.DRepID => + // eslint-disable-next-line new-cap + Cardano.DRepID(HexBlob.toTypedBech32('drep', HexBlob(value))); diff --git a/packages/cardano/src/wallet/util/index.ts b/packages/cardano/src/wallet/util/index.ts index 81841df4e..6bab1d105 100644 --- a/packages/cardano/src/wallet/util/index.ts +++ b/packages/cardano/src/wallet/util/index.ts @@ -3,3 +3,5 @@ export * from './observable'; export * from './asset-balance'; export * from './stake-pool-transformer'; export * from './calculate-deposit-reclaim'; +export * from './drep'; +export * from './voter'; diff --git a/packages/cardano/src/wallet/util/voter.ts b/packages/cardano/src/wallet/util/voter.ts new file mode 100644 index 000000000..32187f66d --- /dev/null +++ b/packages/cardano/src/wallet/util/voter.ts @@ -0,0 +1,97 @@ +import { Cardano } from '@cardano-sdk/core'; +import { drepIDasBech32FromHash } from './drep'; + +const { VoterType, Vote } = Cardano; + +export enum VoterTypeEnum { + CONSTITUTIONAL_COMMITTEE = 'constitutionalCommittee', + SPO = 'spo', + DREP = 'drep' +} + +export const getVoterType = (voterType: Cardano.VoterType): VoterTypeEnum => { + switch (voterType) { + case VoterType.ccHotKeyHash: + case VoterType.ccHotScriptHash: + return VoterTypeEnum.CONSTITUTIONAL_COMMITTEE; + case VoterType.stakePoolKeyHash: + return VoterTypeEnum.SPO; + case VoterType.dRepKeyHash: + case VoterType.dRepScriptHash: + return VoterTypeEnum.DREP; + default: + return VoterTypeEnum.DREP; + } +}; + +export const getDRepId = (voter: Cardano.Voter): Cardano.DRepID | string => + getVoterType(voter.__typename) === VoterTypeEnum.DREP + ? drepIDasBech32FromHash(voter.credential.hash) + : voter.credential.hash.toString(); + +export enum VotesEnum { + YES = 'yes', + NO = 'no', + ABSTAIN = 'abstain' +} + +export const getVote = (vote: Cardano.Vote): VotesEnum => { + switch (vote) { + case Vote.yes: + return VotesEnum.YES; + case Vote.no: + return VotesEnum.NO; + case Vote.abstain: + default: + return VotesEnum.ABSTAIN; + } +}; + +type VotingProcedureView = { + voter: { + type: VoterTypeEnum; + dRepId?: string; + }; + votes: { + actionId: { + index: number; + txHash: string; + txHashUrl?: string; + }; + votingProcedure: { + vote: VotesEnum; + anchor: { + url: string; + hash: string; + } | null; + }; + }[]; +}; + +export const mapVotingProcedureToView = ( + votingProcedure: Cardano.VotingProcedures[number], + explorerBaseUrl: string +): VotingProcedureView => { + const voterType = getVoterType(votingProcedure.voter.__typename); + + return { + voter: { + type: voterType, + dRepId: getDRepId(votingProcedure.voter) + }, + votes: votingProcedure.votes.map((vote) => ({ + actionId: { + index: vote.actionId.actionIndex, + txHash: vote.actionId.id.toString(), + txHashUrl: `${explorerBaseUrl}/${vote.actionId.id}` + }, + votingProcedure: { + vote: getVote(vote.votingProcedure.vote), + anchor: !!vote.votingProcedure.anchor && { + url: vote.votingProcedure.anchor.url, + hash: vote.votingProcedure.anchor.dataHash.toString() + } + } + })) + }; +}; diff --git a/packages/common/src/analytics/types.ts b/packages/common/src/analytics/types.ts index 06f84c672..3bb2af515 100644 --- a/packages/common/src/analytics/types.ts +++ b/packages/common/src/analytics/types.ts @@ -116,7 +116,6 @@ export enum PostHogAction { StakingBrowsePoolsMoreOptionsSortingLiveStakeClick = 'staking | browse pools | more options sorting | live-stake | click', StakingBrowsePoolsTickerClick = 'staking | browse pools | ticker | click', StakingBrowsePoolsSaturationClick = 'staking | browse pools | saturation | click', - StakingBrowsePoolsROSClick = 'staking | browse pools | ros | click', StakingBrowsePoolsCostClick = 'staking | browse pools | cost | click', StakingBrowsePoolsMarginClick = 'staking | browse pools | margin | click', StakingBrowsePoolsProducedBlocksClick = 'staking | browse pools | produced blocks | click', @@ -248,6 +247,10 @@ export enum PostHogAction { TokenTokensTokenRowClick = 'token | tokens | token row | click', TokenTokenDetailViewAllClick = 'token | token detail | view all | click', TokenTokenDetailXClick = 'token | token detail | x | click', + TokenTokensTopYourWalletBuyAdaClick = 'token | tokens | top your wallet | buy ada | click', + TokenBuyAdaDisclaimerGoBackClick = 'token | buy ada | disclaimer | go back | click', + TokenBuyAdaDisclaimerAgreeClick = 'token | buy ada | disclaimer | agree | click', + TokenBuyAdaDisclaimerContinueClick = 'token | buy ada | disclaimer | continue | click', // Activities ActivityActivityClick = 'activity | activity | click', ActivityActivityActivityRowClick = 'activity | activity | activity row | click', diff --git a/packages/core/.storybook/__mocks__/cardano.ts b/packages/core/.storybook/__mocks__/cardano.ts index 7c65b255b..2544ef6d9 100644 --- a/packages/core/.storybook/__mocks__/cardano.ts +++ b/packages/core/.storybook/__mocks__/cardano.ts @@ -1,10 +1,15 @@ import { Cardano, util } from '@cardano-sdk/core'; -import * as WalletUtil from '../../../cardano/src/wallet/util'; +import * as Crypto from '@cardano-sdk/crypto'; + +import * as cardanoUtils from '../../../cardano/src/wallet/util'; +import * as drep from '../../../cardano/src/wallet/util/drep'; export const Wallet = { util: { ...util, - ...WalletUtil + ...cardanoUtils, + ...drep }, - Cardano + Cardano, + Crypto }; diff --git a/packages/core/src/ui/components/ActivityDetail/TransactionDetails.stories.tsx b/packages/core/src/ui/components/ActivityDetail/TransactionDetails.stories.tsx index 97acb4e7b..755917e1d 100644 --- a/packages/core/src/ui/components/ActivityDetail/TransactionDetails.stories.tsx +++ b/packages/core/src/ui/components/ActivityDetail/TransactionDetails.stories.tsx @@ -6,7 +6,18 @@ import { TransactionDetails } from './TransactionDetails'; import { ComponentProps } from 'react'; import { ActivityStatus } from '../Activity/AssetActivityItem'; import { Wallet } from '@lace/cardano'; -import { ConwayEraCertificatesTypes } from './types'; +import { mockProposalProcedure } from '@src/ui/utils'; +import { mockVotingProcedures } from '@src/ui/utils/voting-procedures-mock'; +const { Cardano, Crypto } = Wallet; +const REWARD_ACCOUNT = Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); +const STAKE_KEY_HASH = Cardano.RewardAccount.toHash(REWARD_ACCOUNT); + +// Storybook doesn't support parameters with BigInt +const DUMMY_DEPOSIT = '100000' as never as bigint; +const KEY_HASH_CREDENTIAL = { + type: Cardano.CredentialType.KeyHash, + hash: Crypto.Hash28ByteBase16(STAKE_KEY_HASH) +}; const meta: Meta = { title: 'Sanchonet/ActivityDetail/TransactionDetails', @@ -53,31 +64,27 @@ const data: ComponentProps = { isPopupView: false, votingProcedures: [], amountTransformer: (amount) => `${Number(amount) * adaPrice} USD`, - openExternalLink: (url) => window.open(url, '_blank', 'noopener,noreferrer'), handleOpenExternalHashLink: () => { console.log('handle on hash click', '639a43144dc2c0ead16f2fb753360f4b4f536502dbdb8aa5e424b00abb7534ff'); }, + chainNetworkId: 0, + cardanoCoin: { + id: '1', + name: 'Cardano', + decimals: 6, + symbol: 'tADA' + }, + explorerBaseUrl: 'some-test-url', ownAddresses: [] }; -const stakeVoteDelegationCertificate = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.StakeVoteDelegation] - }, - { - title: 'stakeKey', - details: ['stake1u929x2y7nnfm797upl7v9rc39pqg87pk5cygvnn2edqmvuq6h48su'] - }, - { - title: 'poolId', - details: ['pool1k0ucs0fau2vhr3p7qh7mnpfgrllwwda7petxjz2gzzaxkyp8f88'] - }, - { - title: 'drep', - details: ['drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp4'] - } -]; +const stakeVoteDelegationCertificate: Wallet.Cardano.StakeVoteDelegationCertificate = { + __typename: Cardano.CertificateType.StakeVoteDelegation, + poolId: Cardano.PoolId('pool126zlx7728y7xs08s8epg9qp393kyafy9rzr89g4qkvv4cv93zem'), + stakeCredential: KEY_HASH_CREDENTIAL, + dRep: KEY_HASH_CREDENTIAL +}; + export const StakeVoteDelegationCertificate: Story = { args: { ...data, @@ -92,25 +99,12 @@ export const StakeVoteDelegationCertificates: Story = { } }; -const stakeRegistrationDelegationCertificate = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.StakeRegistrationDelegation] - }, - { - title: 'stakeKey', - details: ['stake1u929x2y7nnfm797upl7v9rc39pqg87pk5cygvnn2edqmvuq6h48su'] - }, - { - title: 'poolId', - details: ['pool1k0ucs0fau2vhr3p7qh7mnpfgrllwwda7petxjz2gzzaxkyp8f88'] - }, - { - title: 'depositPaid', - info: 'depositPaidInfo', - details: [['2.00 ADA', '0.08 USD']] - } -]; +const stakeRegistrationDelegationCertificate: Wallet.Cardano.StakeRegistrationDelegationCertificate = { + __typename: Cardano.CertificateType.StakeRegistrationDelegation, + deposit: DUMMY_DEPOSIT, + poolId: Cardano.PoolId('pool1syqhydhdzcuqhwtt6q4m63f9g8e7262wzsvk7e0r0njsyjyd0yn'), + stakeCredential: KEY_HASH_CREDENTIAL +}; export const StakeRegistrationDelegationCertificate: Story = { args: { @@ -120,25 +114,12 @@ export const StakeRegistrationDelegationCertificate: Story = { } }; -const voteRegistrationDelegationCertificate = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.VoteRegistrationDelegation] - }, - { - title: 'stakeKey', - details: ['stake1u929x2y7nnfm797upl7v9rc39pqg87pk5cygvnn2edqmvuq6h48su'] - }, - { - title: 'drepId', - details: ['drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp4'] - }, - { - title: 'depositPaid', - info: 'depositPaidInfo', - details: [['2.00 ADA', '0.08 USD']] - } -]; +const voteRegistrationDelegationCertificate: Wallet.Cardano.VoteRegistrationDelegationCertificate = { + __typename: Cardano.CertificateType.VoteRegistrationDelegation, + stakeCredential: KEY_HASH_CREDENTIAL, + dRep: KEY_HASH_CREDENTIAL, + deposit: DUMMY_DEPOSIT +}; export const VoteRegistrationDelegationCertificate: Story = { args: { @@ -148,29 +129,13 @@ export const VoteRegistrationDelegationCertificate: Story = { } }; -const stakeVoteRegistrationDelegationCertificate = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.StakeVoteRegistrationDelegation] - }, - { - title: 'stakeKey', - details: ['stake1u929x2y7nnfm797upl7v9rc39pqg87pk5cygvnn2edqmvuq6h48su'] - }, - { - title: 'poolId', - details: ['pool1k0ucs0fau2vhr3p7qh7mnpfgrllwwda7petxjz2gzzaxkyp8f88'] - }, - { - title: 'drepId', - details: ['drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp4'] - }, - { - title: 'depositPaid', - info: 'depositPaidInfo', - details: [['2.00 ADA', '0.08 USD']] - } -]; +const stakeVoteRegistrationDelegationCertificate: Wallet.Cardano.StakeVoteRegistrationDelegationCertificate = { + __typename: Cardano.CertificateType.StakeVoteRegistrationDelegation, + poolId: Cardano.PoolId('pool126zlx7728y7xs08s8epg9qp393kyafy9rzr89g4qkvv4cv93zem'), + stakeCredential: KEY_HASH_CREDENTIAL, + dRep: KEY_HASH_CREDENTIAL, + deposit: DUMMY_DEPOSIT +}; export const StakeVoteRegistrationDelegationCertificate: Story = { args: { @@ -180,26 +145,14 @@ export const StakeVoteRegistrationDelegationCertificate: Story = { } }; -const updateDRep = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.UpdateDelegateRepresentative] - }, - { - title: 'drepId', - details: ['65ge6g54g5dd5'] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] +const updateDRep: Wallet.Cardano.UpdateDelegateRepresentativeCertificate = { + __typename: Cardano.CertificateType.UpdateDelegateRepresentative, + dRepCredential: KEY_HASH_CREDENTIAL, + anchor: { + url: 'anchorUrl', + dataHash: Crypto.Hash32ByteBase16(Buffer.from('anchorDataHashanchorDataHashanch').toString('hex')) } -]; +}; export const UpdateDRep: Story = { name: 'Update DRep', @@ -210,26 +163,14 @@ export const UpdateDRep: Story = { } }; -const resignCommittee = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.ResignCommitteeCold] - }, - { - title: 'coldCredential', - details: ['65ge6g54g5dd5'] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] +const resignCommittee: Wallet.Cardano.ResignCommitteeColdCertificate = { + __typename: Cardano.CertificateType.ResignCommitteeCold, + coldCredential: KEY_HASH_CREDENTIAL, + anchor: { + url: 'anchorUrl', + dataHash: Crypto.Hash32ByteBase16(Buffer.from('anchorDataHashanchorDataHashanch').toString('hex')) } -]; +}; export const ResignCommittee: Story = { args: { @@ -239,20 +180,11 @@ export const ResignCommittee: Story = { } }; -const authorizeCommittee = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.AuthorizeCommitteeHot] - }, - { - title: 'coldCredential', - details: ['cc_cold 65ge6g54g5dd5'] - }, - { - title: 'hotCredential', - details: ['cc_hot stake1u929x2y7nnfm797upl7v9rc39pqg87pk5cygvnn2edqmvuq6h48su'] - } -]; +const authorizeCommittee: Wallet.Cardano.AuthorizeCommitteeHotCertificate = { + __typename: Cardano.CertificateType.AuthorizeCommitteeHot, + coldCredential: KEY_HASH_CREDENTIAL, + hotCredential: KEY_HASH_CREDENTIAL +}; export const AuthorizeCommittee: Story = { args: { @@ -262,31 +194,15 @@ export const AuthorizeCommittee: Story = { } }; -const dRepRegistration = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.RegisterDelegateRepresentative] - }, - { - title: 'drepId', - details: ['drep170ef53apap7dadzemkcd7lujlzk5hyzvzzjj7f3sx89ecn3ft6u'] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] - }, - { - title: 'depositPaid', - info: 'depositPaidInfo', - details: [['0.35 ADA', '0.08 USD']] +const dRepRegistration: Wallet.Cardano.RegisterDelegateRepresentativeCertificate = { + __typename: Cardano.CertificateType.RegisterDelegateRepresentative, + dRepCredential: KEY_HASH_CREDENTIAL, + deposit: DUMMY_DEPOSIT, + anchor: { + url: 'anchorUrl', + dataHash: Crypto.Hash32ByteBase16(Buffer.from('anchorDataHashanchorDataHashanch').toString('hex')) } -]; +}; export const DRepRegistration: Story = { name: 'DRep Registration', @@ -297,21 +213,11 @@ export const DRepRegistration: Story = { } }; -const dRepDeRegistration = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.UnregisterDelegateRepresentative] - }, - { - title: 'drepId', - details: ['drep170ef53apap7dadzemkcd7lujlzk5hyzvzzjj7f3sx89ecn3ft6u'] - }, - { - title: 'depositReturned', - info: 'depositReturnedInfo', - details: [['0.35 ADA', '0.08 USD']] - } -]; +const dRepDeRegistration: Wallet.Cardano.UnRegisterDelegateRepresentativeCertificate = { + __typename: Cardano.CertificateType.UnregisterDelegateRepresentative, + dRepCredential: KEY_HASH_CREDENTIAL, + deposit: DUMMY_DEPOSIT +}; export const DRepDeRegistration: Story = { name: 'DRep De-Registration', @@ -322,20 +228,11 @@ export const DRepDeRegistration: Story = { } }; -const voteDelegation = [ - { - title: 'certificateType', - details: [ConwayEraCertificatesTypes.VoteDelegation] - }, - { - title: 'stakeKey', - details: ['stake1u929x2y7nnfm797upl7v9rc39pqg87pk5cygvnn2edqmvuq6h48su'] - }, - { - title: 'drepId', - details: ['drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp4'] - } -]; +const voteDelegation: Wallet.Cardano.VoteDelegationCertificate = { + __typename: Cardano.CertificateType.VoteDelegation, + dRep: { __typename: 'AlwaysAbstain' }, + stakeCredential: KEY_HASH_CREDENTIAL +}; export const VoteDelegation: Story = { args: { @@ -345,575 +242,67 @@ export const VoteDelegation: Story = { } }; -const confirmVote = [ - { - title: 'voterType', - details: ['drep'] - }, - { - title: 'voterCredential', - details: ['drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp4'] - }, - { - title: 'voteTypes', - details: ['yes'] - }, - { - title: 'anchorURL', - details: ['https://shorturl.at/eK145'] - }, - { - title: 'anchorHash', - details: ['9067f223838d88b83f660c05eedf7f6f65c45de31e522c1bcb6a1eb287b17e89'] - } -]; - export const ConfirmVote: Story = { args: { ...data, name: 'Confirm Vote', - votingProcedures: [confirmVote, confirmVote] + votingProcedures: mockVotingProcedures, + explorerBaseUrl: 'https://some-test-url.io' } }; -const parameterChangeAction = [ - { - title: 'type', - details: [Wallet.Cardano.GovernanceActionType.parameter_change_action] - }, - { - title: 'deposit', - details: ['stake1u89sa...css5vgr'] - }, - { - title: 'rewardAccount', - details: ['https://www.someurl.io'] - }, - { - title: 'anchorURL', - details: ['https://www.someurl.io'] - }, - { - title: 'anchorHash', - details: ['000000...0000'] - }, - { - header: 'maxTxExUnits', - details: [ - { - title: 'memory', - details: ['100000000'] - }, - { - title: 'step', - details: ['10000000000000'] - } - ] - }, - { - header: 'maxBlockExUnits', - details: [ - { - title: 'memory', - details: ['50000000'] - }, - { - title: 'step', - details: ['40000000000'] - } - ] - }, - { - header: 'networkGroup', - details: [ - { - title: 'maxBBSize', - details: ['65536'] - }, - { - title: 'maxTxSize', - details: ['16384'] - }, - { - title: 'maxBHSize', - details: ['1100'] - }, - { - title: 'maxValSize', - details: ['5000'] - }, - { - title: 'maxCollateralInputs', - details: ['3'] - } - ] - }, - { - header: 'economicGroup', - details: [ - { - title: 'minFeeA', - details: ['44'] - }, - { - title: 'minFeeB', - details: ['155381'] - }, - { - title: 'keyDeposit', - details: ['2000000'] - }, - { - title: 'poolDeposit', - details: ['500000000'] - }, - { - title: 'rho', - details: ['0.003'] - }, - { - title: 'tau', - details: ['0.2'] - }, - { - title: 'minPoolCost', - details: ['340000000'] - }, - { - title: 'coinsPerUTxOByte', - details: ['34482'] - } - ] - }, - { - header: 'costModels', - details: [ - { - title: 'PlutusV1', - details: ['197209'] - }, - { - title: 'PlutusV2', - details: ['197209'] - } - ] - }, - { - header: 'technicalGroup', - details: [ - { - title: 'a0', - details: ['0.3'] - }, - { - title: 'eMax', - details: ['18'] - }, - { - title: 'nOpt', - details: ['150'] - }, - { - title: 'collateralPercentage', - details: ['150'] - } - ] - }, - { - header: 'prices', - details: [ - { - title: 'memory', - details: ['0.0577'] - }, - { - title: 'step', - details: ['0.0000721'] - } - ] - }, - { - header: 'governanceGroup', - details: [ - { - title: 'govActionLifetime', - details: ['10'] - }, - { - title: 'govActionDeposit', - details: ['500 ADA'] - }, - { - title: 'drepDeposit', - details: ['1000 ADA'] - }, - { - title: 'drepActivity', - details: ['5'] - }, - { - title: 'ccMinSize', - details: ['7'] - }, - { - title: 'ccMaxTermLength', - details: ['25'] - } - ] - }, - { - header: 'dRepVotingThresholds', - details: [ - { - title: 'motionNoConfidence', - details: ['51%'] - }, - { - title: 'committeeNormal', - details: ['67%'] - }, - { - title: 'committeeNoConfidence', - details: ['80%'] - }, - { - title: 'updateConstitution', - details: ['75%'] - }, - { - title: 'hardForkInitiation', - details: ['90%'] - }, - { - title: 'ppNetworkGroup', - details: ['70%'] - }, - { - title: 'ppEconomicGroup', - details: ['70%'] - }, - { - title: 'ppTechnicalGroup', - details: ['70%'] - }, - { - title: 'ppGovernanceGroup', - details: ['70%'] - }, - { - title: 'treasuryWithdrawal', - details: ['51%'] - } - ] - } -]; - export const ParameterChangeAction: Story = { args: { ...data, name: 'Parameter Change Action', - proposalProcedures: [parameterChangeAction] + proposalProcedures: [mockProposalProcedure[Cardano.GovernanceActionType.parameter_change_action]] } }; -const hardForkInitiationAction = [ - { - title: 'type', - details: [Wallet.Cardano.GovernanceActionType.hard_fork_initiation_action] - }, - { - title: 'deposit', - info: 'deposit', - details: [['2.00 ADA', '0.18 USD']] - }, - { title: 'rewardAccount', details: ['23bcf2892e8182a68e3aac6f9f42ed3317d115ebad12a17232681175'] }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'governanceActionID', - details: ['d0b1f7be72731a97e9728e0f1c358d576fd28aa9f290d53ce1ef803a1a753ba8'] - }, - { - title: 'actionIndex', - details: ['0'] - }, - { - title: 'protocolVersionMajor', - details: ['1'] - }, - { - title: 'protocolVersionMinor', - details: ['2'] - }, - { - title: 'protocolVersionPatch', - details: ['3'] - } -]; - export const HardForkInitiationAction: Story = { args: { ...data, name: 'Hard Fork Initiation Action', - proposalProcedures: [hardForkInitiationAction] + proposalProcedures: [mockProposalProcedure[Cardano.GovernanceActionType.hard_fork_initiation_action]] } }; -const infoAction = [ - { - title: 'type', - details: [Wallet.Cardano.GovernanceActionType.info_action] - }, - { - title: 'deposit', - info: 'deposit', - details: [['2.00 ADA', '0.18 USD']] - }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'governanceActionID', - details: ['d0b1f7be72731a97e9728e0f1c358d576fd28aa9f290d53ce1ef803a1a753ba8'] - }, - { - title: 'actionIndex', - details: ['0'] - } -]; - export const InfoAction: Story = { args: { ...data, name: 'Info Action', - proposalProcedures: [infoAction] + proposalProcedures: [mockProposalProcedure[Cardano.GovernanceActionType.info_action]] } }; -const newConstitutionAction = [ - { - title: 'type', - details: [Wallet.Cardano.GovernanceActionType.new_constitution] - }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'governanceActionID', - details: ['d0b1f7be72731a97e9728e0f1c358d576fd28aa9f290d53ce1ef803a1a753ba8'] - }, - { - title: 'actionIndex', - details: ['0'] - }, - { - title: 'constitutionAnchorURL', - details: ['https://www.someurl.io'] - }, - { - title: 'constitutionScriptHash', - details: ['cb0ec2692497b458e46812c8a5bfa2931d1a2d965a99893828ec810f'] - } -]; - export const NewConstitutionAction: Story = { args: { ...data, name: 'New Constitution Action', - proposalProcedures: [newConstitutionAction] + proposalProcedures: [mockProposalProcedure[Cardano.GovernanceActionType.new_constitution]] } }; -const noConfidenceAction = [ - { - title: 'type', - details: [Wallet.Cardano.GovernanceActionType.no_confidence] - }, - { - title: 'deposit', - info: 'deposit', - details: [['2.00 ADA', '0.18 USD']] - }, - { title: 'rewardAccount', details: ['23bcf2892e8182a68e3aac6f9f42ed3317d115ebad12a17232681175'] }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'governanceActionID', - details: ['d0b1f7be72731a97e9728e0f1c358d576fd28aa9f290d53ce1ef803a1a753ba8'] - }, - { - title: 'actionIndex', - details: ['0'] - } -]; - export const NoConfidenceAction: Story = { args: { ...data, name: 'No Confidence Action', - proposalProcedures: [noConfidenceAction] + proposalProcedures: [mockProposalProcedure[Cardano.GovernanceActionType.no_confidence]] } }; -const updateCommitteeAction = [ - { - title: 'type', - details: [Wallet.Cardano.GovernanceActionType.update_committee] - }, - { - title: 'deposit', - info: 'deposit', - details: [['2.00 ADA', '0.18 USD']] - }, - { title: 'rewardAccount', details: ['23bcf2892e8182a68e3aac6f9f42ed3317d115ebad12a17232681175'] }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'governanceActionID', - details: ['d0b1f7be72731a97e9728e0f1c358d576fd28aa9f290d53ce1ef803a1a753ba8'] - }, - { - title: 'actionIndex', - details: ['0'] - }, - { - header: 'membersToBeAdded', - details: [ - { - title: 'coldCredentialHash', - details: ['30000000000000000000000000000000000000000000000000000000'] - }, - { - title: 'epoch', - details: ['1'] - }, - { - title: 'coldCredentialHash', - details: ['40000000000000000000000000000000000000000000000000000000'] - }, - { - title: 'epoch', - details: ['2'] - } - ] - }, - { - header: 'membersToBeRemoved', - details: [ - { - title: 'hash', - details: ['00000000000000000000000000000000000000000000000000000000'] - } - ] - }, - { - title: 'newQuorumThreshold', - details: ['0.4%'] - } -]; - export const UpdateCommitteeAction: Story = { args: { ...data, name: 'Update Committee Action', - proposalProcedures: [updateCommitteeAction] + proposalProcedures: [mockProposalProcedure[Cardano.GovernanceActionType.update_committee]] } }; -const treasuryWithdrawalsAction = [ - { - title: 'type', - details: [Wallet.Cardano.GovernanceActionType.treasury_withdrawals_action] - }, - { - title: 'deposit', - info: 'deposit', - details: [['2.00 ADA', '0.18 USD']] - }, - { title: 'rewardAccount', details: ['23bcf2892e8182a68e3aac6f9f42ed3317d115ebad12a17232681175'] }, - { - title: 'anchorURL', - details: [ - 'https://raw.githubusercontent.com/Ryun1/gov-metadata/main/governace-action/metadata.jsonldr1q99...uqvzlalu' - ] - }, - { - title: 'anchorHash', - details: ['3d2a9d15382c14f5ca260a2f5bfb645fe148bfe10c1d0e1d305b7b1393e2bd97'] - }, - { - title: 'governanceActionID', - details: ['d0b1f7be72731a97e9728e0f1c358d576fd28aa9f290d53ce1ef803a1a753ba8'] - }, - { - title: 'actionIndex', - details: ['0'] - }, - { - header: 'withdrawal', - details: [ - { - title: 'withdrawalRewardAccount', - details: ['23bcf2892e8182a68e3aac6f9f42ed3317d115ebad12a17232681175'] - }, - { - title: 'withdrawalAmount', - details: ['1030939916423 ADA'] - }, - { - title: 'withdrawalRewardAccount', - details: ['23bcf2892e8182a68e3aac6f9f42ed3317d115ebad12a17232681175'] - }, - { - title: 'withdrawalAmount', - details: ['1030939916423 ADA'] - } - ] - } -]; - export const TreasuryWithdrawalsAction: Story = { args: { ...data, name: 'Treasury Withdrawals Action', - proposalProcedures: [treasuryWithdrawalsAction] + proposalProcedures: [mockProposalProcedure[Cardano.GovernanceActionType.treasury_withdrawals_action]] } }; diff --git a/packages/core/src/ui/components/ActivityDetail/TransactionDetails.tsx b/packages/core/src/ui/components/ActivityDetail/TransactionDetails.tsx index e3b1460ff..f9c6c3b37 100644 --- a/packages/core/src/ui/components/ActivityDetail/TransactionDetails.tsx +++ b/packages/core/src/ui/components/ActivityDetail/TransactionDetails.tsx @@ -13,18 +13,13 @@ import styles from './TransactionDetails.module.scss'; import { TransactionInputOutput } from './TransactionInputOutput'; import { TransactionFee } from './TransactionFee'; import { ActivityDetailHeader } from './ActivityDetailHeader'; -import { TxDetailList } from './TxDetailsList'; -import { - TxDetailsVotingProceduresTitles, - TxDetailsProposalProceduresTitles, - TxDetailsCertificateTitles, - TxDetails, - TxDetail, - TransactionActivityType -} from './types'; import { Collateral, CollateralStatus } from './Collateral'; +import { Wallet } from '@lace/cardano'; +import { TxDetailsCertificates } from './components/TxDetailsCertificates/TxDetailsCertificates'; +import { TxDetailsVotingProcedures } from './components/TxDetailsVotingProcedures'; +import { TxDetailsProposalProcedures } from './components/TxDetailsProposalProcedures'; +import { TransactionActivityType } from './types'; import { useTranslation } from 'react-i18next'; -import { TranslationKey } from '@lace/translation'; // eslint-disable-next-line @typescript-eslint/no-explicit-any const displayMetadataMsg = (value: any[]): string => value?.find((val: any) => val.hasOwnProperty('msg'))?.msg || ''; @@ -83,13 +78,15 @@ export interface TransactionDetailsProps { ownAddresses: string[]; addressToNameMap: Map; isPopupView?: boolean; - openExternalLink?: (url: string) => void; handleOpenExternalHashLink?: () => void; sendAnalyticsInputs?: () => void; sendAnalyticsOutputs?: () => void; - votingProcedures?: TxDetails[]; - proposalProcedures?: TxDetails[]; - certificates?: TxDetails[]; + votingProcedures?: Wallet.Cardano.VotingProcedures; + proposalProcedures?: Wallet.Cardano.ProposalProcedure[]; + certificates?: Wallet.Cardano.Certificate[]; + chainNetworkId: Wallet.Cardano.NetworkId; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; } const TOAST_DEFAULT_DURATION = 3; @@ -130,107 +127,22 @@ export const TransactionDetails = ({ ownAddresses, addressToNameMap, isPopupView, - openExternalLink, handleOpenExternalHashLink, sendAnalyticsInputs, sendAnalyticsOutputs, proposalProcedures, votingProcedures, + collateral, certificates, - collateral + chainNetworkId, + cardanoCoin, + explorerBaseUrl }: TransactionDetailsProps): React.ReactElement => { const { t } = useTranslation(); const isSending = status === ActivityStatus.PENDING; const isSuccess = status === ActivityStatus.SUCCESS; - const renderAnchorHashDetails = (url: string) => ( -
openExternalLink(url)}> - {url} -
- ); - - // Translate certificate typenames - // TODO: refactor this one - const translatedCertificates = certificates?.map((certificate) => - certificate?.map( - (detail) => - ({ - ...detail, - ...('title' in detail && - detail.title === 'certificateType' && { - details: [t(`core.assetActivityItem.entry.name.${detail.details[0]}` as unknown as TranslationKey)] - }), - ...('title' in detail && - detail.title === 'anchorURL' && { - details: [renderAnchorHashDetails(detail.details[0] as string)] - }) - } as unknown as TxDetail) - ) - ); - - // Translate governance proposal typenames - // TODO: find a way to translate in the mappers - // TODO: refactor this one - const translatedProposalProcedures = proposalProcedures?.map((proposal) => - proposal?.map( - (p) => - ({ - ...p, - ...('title' in p && - p.title === 'type' && { - details: [t(`core.activityDetails.governanceActions.${p.details[0]}` as unknown as TranslationKey)] - }), - ...('title' in p && - p.title === 'anchorURL' && { - details: [renderAnchorHashDetails(p.details[0] as string)] - }), - ...('header' in p && { - details: p.details.map((detail) => ({ - ...detail, - ...('title' in detail && - ['govActionLifetime', 'drepActivity', 'ccMaxTermLength'].includes(detail.title) && { - details: [ - ` - ${Number(detail.details[0])} - ${t( - // eslint-disable-next-line sonarjs/no-nested-template-literals - `core.activityDetails.${ - Number(detail.details[0]) === 0 || Number(detail.details[0]) > 1 ? 'epochs' : 'epoch' - }` - )} - ` - ] - }), - ...('title' in detail && - detail.title === 'anchorURL' && { - details: [renderAnchorHashDetails(detail.details[0] as string)] - }) - })) - }) - } as unknown as TxDetail) - ) - ); - - // Translate voting procedure typenames - // TODO: refactor this one - const translatedVotingProcedures = votingProcedures?.map((proposal) => - proposal?.map( - (p) => - ({ - ...p, - ...('title' in p && - ['voterType', 'voteTypes'].includes(p.title) && { - details: [t(`core.activityDetails.${p.title}.${p.details[0]}` as unknown as TranslationKey)] - }), - ...('title' in p && - p.title === 'anchorURL' && { - details: [renderAnchorHashDetails(p.details[0] as string)] - }) - } as unknown as TxDetail) - ) - ); - const getCollateralStatus = (): CollateralStatus => { switch (status) { case ActivityStatus.SPENDABLE: @@ -430,163 +342,21 @@ export const TransactionDetails = ({ label: t('core.activityDetails.depositReclaim') })} - {votingProcedures?.length > 0 && ( - - testId="voting-procedures" - title={t('core.activityDetails.votingProcedures')} - subTitle={t('core.activityDetails.votingProcedure')} - lists={translatedVotingProcedures} - translations={{ - voterType: t('core.activityDetails.votingProcedureTitles.voterType'), - drepId: t('core.activityDetails.votingProcedureTitles.drepId'), - voterCredential: t('core.activityDetails.votingProcedureTitles.voterCredential'), - voteTypes: t('core.activityDetails.votingProcedureTitles.voteTypes'), - anchorHash: t('core.activityDetails.votingProcedureTitles.anchorHash'), - anchorURL: t('core.activityDetails.votingProcedureTitles.anchorURL') - }} - withSeparatorLine - /> + )} {proposalProcedures?.length > 0 && ( - - testId="proposal-procedures" - title={t('core.activityDetails.proposalProcedures')} - subTitle={t('core.activityDetails.proposalProcedure')} - lists={translatedProposalProcedures} - withSeparatorLine - translations={{ - type: t('core.activityDetails.proposalProcedureTitles.type'), - deposit: t('core.activityDetails.proposalProcedureTitles.deposit'), - rewardAccount: t('core.activityDetails.proposalProcedureTitles.rewardAccount'), - anchorHash: t('core.activityDetails.proposalProcedureTitles.anchorHash'), - anchorURL: t('core.activityDetails.proposalProcedureTitles.anchorURL'), - governanceActionID: t('core.activityDetails.proposalProcedureTitles.governanceActionID'), - actionIndex: t('core.activityDetails.proposalProcedureTitles.actionIndex'), - newQuorumThreshold: t('core.activityDetails.proposalProcedureTitles.newQuorumThreshold'), - withdrawal: t('core.activityDetails.proposalProcedureTitles.withdrawal'), - withdrawalRewardAccount: t('core.activityDetails.proposalProcedureTitles.withdrawalRewardAccount'), - withdrawalAmount: t('core.activityDetails.proposalProcedureTitles.withdrawalAmount'), - constitutionAnchorURL: t('core.activityDetails.proposalProcedureTitles.constitutionAnchorURL'), - constitutionScriptHash: t('core.activityDetails.proposalProcedureTitles.constitutionScriptHash'), - coldCredentialHash: t('core.activityDetails.proposalProcedureTitles.coldCredentialHash'), - epoch: t('core.activityDetails.proposalProcedureTitles.epoch'), - membersToBeAdded: t('core.activityDetails.proposalProcedureTitles.membersToBeAdded'), - hash: t('core.activityDetails.proposalProcedureTitles.hash'), - membersToBeRemoved: t('core.activityDetails.proposalProcedureTitles.membersToBeRemoved'), - protocolVersionMajor: t('core.activityDetails.proposalProcedureTitles.protocolVersionMajor'), - protocolVersionMinor: t('core.activityDetails.proposalProcedureTitles.protocolVersionMinor'), - protocolVersionPatch: t('core.activityDetails.proposalProcedureTitles.protocolVersionPatch'), - maxTxExUnits: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxTxExUnits'), - maxBlockExUnits: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBlockExUnits' - ), - networkGroup: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.title'), - economicGroup: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.title'), - technicalGroup: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.title'), - costModels: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.costModels'), - PlutusV1: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.PlutusV1'), - PlutusV2: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.PlutusV2'), - governanceGroup: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.title'), - dRepVotingThresholds: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.title' - ), - memory: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.memory'), - step: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.step'), - maxBBSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBBSize'), - maxTxSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxTxSize'), - maxBHSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBHSize'), - maxValSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxValSize'), - maxCollateralInputs: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxCollateralInputs' - ), - minFeeA: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minFeeA'), - minFeeB: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minFeeB'), - keyDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.keyDeposit'), - poolDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.poolDeposit'), - rho: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.rho'), - tau: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tau'), - minPoolCost: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minPoolCost'), - coinsPerUTxOByte: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.coinsPerUTxOByte' - ), - a0: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.a0'), - eMax: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.eMax'), - nOpt: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.nOpt'), - collateralPercentage: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.collateralPercentage' - ), - prices: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.prices'), - govActionLifetime: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.govActionLifetime' - ), - govActionDeposit: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.govActionDeposit' - ), - drepDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.drepDeposit'), - drepActivity: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.drepActivity' - ), - ccMinSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.ccMinSize'), - ccMaxTermLength: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.ccMaxTermLength' - ), - motionNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.motionNoConfidence' - ), - committeeNormal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.committeeNormal' - ), - committeeNoConfidence: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.committeeNoConfidence' - ), - updateConstitution: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.updateConstitution' - ), - hardForkInitiation: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.hardForkInitiation' - ), - ppNetworkGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppNetworkGroup' - ), - ppEconomicGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppEconomicGroup' - ), - ppTechnicalGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppTechnicalGroup' - ), - ppGovernanceGroup: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppGovernanceGroup' - ), - treasuryWithdrawal: t( - 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.treasuryWithdrawal' - ) - }} + )} {certificates?.length > 0 && ( - - title={t('core.activityDetails.certificates')} - subTitle={t('core.activityDetails.certificate')} - testId="certificates" - lists={translatedCertificates} - withSeparatorLine - translations={{ - certificate: t('core.activityDetails.certificateTitles.certificate'), - certificateType: t('core.activityDetails.certificateTitles.certificateType'), - coldCredential: t('core.activityDetails.certificateTitles.coldCredential'), - hotCredential: t('core.activityDetails.certificateTitles.hotCredential'), - stakeKey: t('core.activityDetails.certificateTitles.stakeKey'), - drepId: t('core.activityDetails.certificateTitles.drepId'), - anchorURL: t('core.activityDetails.certificateTitles.anchorURL'), - anchorHash: t('core.activityDetails.certificateTitles.anchorHash'), - poolId: t('core.activityDetails.certificateTitles.poolId'), - drep: t('core.activityDetails.certificateTitles.drep'), - depositPaid: t('core.activityDetails.certificateTitles.depositPaid'), - depositPaidInfo: t('core.activityDetails.certificateTitles.depositPaidInfo'), - depositReturned: t('core.activityDetails.certificateTitles.depositReturned'), - depositReturnedInfo: t('core.activityDetails.certificateTitles.depositReturnedInfo') - }} + )} {addrInputs?.length > 0 && ( diff --git a/packages/core/src/ui/components/ActivityDetail/TxDetailsList.tsx b/packages/core/src/ui/components/ActivityDetail/TxDetailsGroup.tsx similarity index 57% rename from packages/core/src/ui/components/ActivityDetail/TxDetailsList.tsx rename to packages/core/src/ui/components/ActivityDetail/TxDetailsGroup.tsx index 330d22638..3b16a6487 100644 --- a/packages/core/src/ui/components/ActivityDetail/TxDetailsList.tsx +++ b/packages/core/src/ui/components/ActivityDetail/TxDetailsGroup.tsx @@ -4,32 +4,25 @@ import cn from 'classnames'; import React, { useState } from 'react'; import { DownOutlined, InfoCircleOutlined } from '@ant-design/icons'; import { Button } from '@lace/common'; -import { TranslationsFor } from '@src/ui/utils/types'; import { ReactComponent as BracketDown } from '../../assets/icons/bracket-down.component.svg'; -import { DetailRows } from './components'; import styles from './TransactionInputOutput.module.scss'; -import { TxDetails } from './types'; import { Text } from '@lace/ui'; -interface TxDetailListProps { +interface TxDetailsGroupProps { testId: string; title: string; - subTitle: string; - lists: TxDetails[]; - translations: T extends string ? TranslationsFor : never; + children: React.ReactNode; tooltipContent?: React.ReactNode; withSeparatorLine?: boolean; } -export const TxDetailList = ({ +export const TxDetailsGroup = ({ testId, title, - subTitle, - lists, + children, tooltipContent, - withSeparatorLine, - translations -}: TxDetailListProps): React.ReactElement => { + withSeparatorLine +}: TxDetailsGroupProps): React.ReactElement => { const [isVisible, setIsVisible] = useState(); const Icon = BracketDown ? ( @@ -64,23 +57,7 @@ export const TxDetailList = ({ className={styles.arrowBtn} /> - {isVisible && ( -
- {lists.map((list, idx) => ( - -
0 })} /> - {lists.length > 1 && ( -
- {`${subTitle} ${ - idx + 1 - }`} -
- )} - translations={translations} testId={testId} list={list} /> - - ))} -
- )} + {isVisible && children}
); }; diff --git a/packages/core/src/ui/components/ActivityDetail/__tests__/TransactionDetails.test.tsx b/packages/core/src/ui/components/ActivityDetail/__tests__/TransactionDetails.test.tsx index 26a3d9558..35d1dc545 100644 --- a/packages/core/src/ui/components/ActivityDetail/__tests__/TransactionDetails.test.tsx +++ b/packages/core/src/ui/components/ActivityDetail/__tests__/TransactionDetails.test.tsx @@ -3,9 +3,17 @@ import * as React from 'react'; import { render, within, fireEvent } from '@testing-library/react'; import '@testing-library/jest-dom'; import { TransactionDetails, TransactionDetailsProps } from '../TransactionDetails'; +import { Wallet } from '@lace/cardano'; const transactionDate = '2021/09/10'; +export const cardanoCoin: Wallet.CoinId = { + id: '1', + name: 'Cardano', + decimals: 6, + symbol: 'A' +}; + describe('Testing ActivityDetailsBrowser component', () => { const addrListProps: TransactionDetailsProps = { name: 'Name', @@ -36,7 +44,10 @@ describe('Testing ActivityDetailsBrowser component', () => { amountTransformer: (amount) => `${amount} $`, coinSymbol: 'ADA', ownAddresses: [], - addressToNameMap: new Map() + addressToNameMap: new Map(), + chainNetworkId: Wallet.Cardano.NetworkId.Testnet, + cardanoCoin, + explorerBaseUrl: '' }; test('should display transaction hash and copy button', async () => { diff --git a/packages/core/src/ui/components/ActivityDetail/components/DetailRow.module.scss b/packages/core/src/ui/components/ActivityDetail/components/DetailRow.module.scss deleted file mode 100644 index 83b9354ec..000000000 --- a/packages/core/src/ui/components/ActivityDetail/components/DetailRow.module.scss +++ /dev/null @@ -1,45 +0,0 @@ -@import '../../../styles/theme.scss'; -@import '../../../../../../common/src/ui/styles/abstracts/typography'; - -.details { - color: var(--text-color-primary, #ffffff); - display: flex; - justify-content: space-between; - margin-bottom: size_unit(4); - width: 100%; - - .title { - align-items: center; - gap: 8px; - display: flex; - flex: 0 0 50%; - align-self: baseline; - color: var(--text-color-primary, #ffffff); - @include text-body-semi-bold; - } - - .detail { - align-items: end; - display: flex; - flex-direction: column; - gap: size_unit(2); - color: var(--text-color-primary, #ffffff); - text-align: right; - word-break: break-all; - @include text-body-medium; - - @media (max-width: $breakpoint-popup) { - flex-direction: column; - } - - .subitems { - display: flex; - flex-direction: column; - width: 100%; - align-items: flex-end; - .subitem { - color: var(--text-color-secondary, #878e9e); - } - } - } -} diff --git a/packages/core/src/ui/components/ActivityDetail/components/DetailRow.tsx b/packages/core/src/ui/components/ActivityDetail/components/DetailRow.tsx deleted file mode 100644 index c70d7c85b..000000000 --- a/packages/core/src/ui/components/ActivityDetail/components/DetailRow.tsx +++ /dev/null @@ -1,31 +0,0 @@ -/* eslint-disable no-magic-numbers */ -import React from 'react'; -import styles from './DetailRow.module.scss'; -import { DetailRowSubitems } from './DetailRowSubitems'; -import { InfoItem } from './InfoItem'; - -type DetailsRowProps = { - title: string; - info?: string; - dataTestId?: string; - details: (string | [string, string])[]; -}; - -// TODO: add proper data mappers, eg: strings, urls, elements, arrays etc -export const DetailRow = ({ title, info, details, dataTestId }: DetailsRowProps): React.ReactElement => ( -
-
- {title} - {info && } -
-
- {details.map((detail, idx) => ( - - {typeof detail === 'string' && detail} - {typeof detail === 'object' && - (detail.length === 2 ? : detail)} - - ))} -
-
-); diff --git a/packages/core/src/ui/components/ActivityDetail/components/DetailRowSubitems.tsx b/packages/core/src/ui/components/ActivityDetail/components/DetailRowSubitems.tsx deleted file mode 100644 index 3adf72383..000000000 --- a/packages/core/src/ui/components/ActivityDetail/components/DetailRowSubitems.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import styles from './DetailRow.module.scss'; - -export interface DetailRowSubitems { - item: string; - subitem: string; - dataTestId?: string; -} -export const DetailRowSubitems = ({ item, subitem, dataTestId }: DetailRowSubitems): React.ReactElement => ( -
- {item} - - {subitem} - -
-); diff --git a/packages/core/src/ui/components/ActivityDetail/components/DetailRows.tsx b/packages/core/src/ui/components/ActivityDetail/components/DetailRows.tsx deleted file mode 100644 index 74ac64329..000000000 --- a/packages/core/src/ui/components/ActivityDetail/components/DetailRows.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React from 'react'; -import cn from 'classnames'; -import { DetailRow } from './DetailRow'; -import { TxDetails } from '../types'; -import { TranslationsFor } from '@src/ui/utils/types'; -import styles from '../TransactionInputOutput.module.scss'; -import { Text } from '@lace/ui'; - -type DetailRowsProps = { - list: TxDetails; - testId: string; - translations: T extends string ? TranslationsFor : never; -}; - -export const DetailRows = function DetailRows({ - list, - testId, - translations -}: DetailRowsProps): React.ReactElement { - return ( - <> - {list?.map((item, index) => - 'title' in item ? ( - - ) : ( - <> -
0 })} - > - - {translations[item.header]} - -
- - - ) - )} - - ); -}; diff --git a/packages/core/src/ui/components/ActivityDetail/components/InfoItem.tsx b/packages/core/src/ui/components/ActivityDetail/components/InfoItem.tsx deleted file mode 100644 index 143510eab..000000000 --- a/packages/core/src/ui/components/ActivityDetail/components/InfoItem.tsx +++ /dev/null @@ -1,19 +0,0 @@ -import React from 'react'; -import { InfoCircleOutlined } from '@ant-design/icons'; -import { Tooltip } from 'antd'; - -import { ReactComponent as Info } from '../../../assets/icons/info-icon.component.svg'; - -export interface InfoItemProps { - title: string; - dataTestId?: string; -} -export const InfoItem = ({ title, dataTestId = '' }: InfoItemProps): React.ReactElement => ( - - {Info ? ( - - ) : ( - - )} - -); diff --git a/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/CertificateView.tsx b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/CertificateView.tsx new file mode 100644 index 000000000..fb87c1150 --- /dev/null +++ b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/CertificateView.tsx @@ -0,0 +1,154 @@ +/* eslint-disable complexity */ +import React from 'react'; +import { Wallet } from '@lace/cardano'; +import { ConfirmStakeRegistrationDelegation } from '@src/ui/components/ConfirmStakeRegistrationDelegation'; +import { ConfirmStakeVoteDelegation } from '@src/ui/components/ConfirmStakeVoteDelegation'; +import { ConfirmStakeVoteRegistrationDelegation } from '@src/ui/components/ConfirmStakeVoteRegistrationDelegation'; +import { ConfirmVoteRegistrationDelegation } from '@src/ui/components/ConfirmVoteRegistrationDelegation'; +import { ConfirmDRepRegistration } from '@src/ui/components/ConfirmDRepRegistration'; +import { ConfirmDRepRetirement } from '@src/ui/components/ConfirmDRepRetirement'; +import { ConfirmDRepUpdate } from '@src/ui/components/ConfirmDRepUpdate'; +import { ConfirmVoteDelegation } from '@src/ui/components/ConfirmVoteDelegation'; +import { AuthorizeCommitteeCertificate } from '@src/ui/components/AuthorizeCommitteeCertificate'; +import { ResignCommitteeCertificate } from '@src/ui/components/ResignCommitteeCertificate'; + +interface CertificateViewProps { + chainNetworkId: Wallet.Cardano.NetworkId; + certificate: Wallet.Cardano.Certificate; + cardanoCoin: Wallet.CoinId; +} + +const { CertificateType, RewardAddress } = Wallet.Cardano; + +export const CertificateView = ({ + certificate, + chainNetworkId, + cardanoCoin +}: CertificateViewProps): React.ReactElement => { + switch (certificate.__typename) { + case CertificateType.StakeVoteDelegation: + return ( + + ); + case CertificateType.StakeRegistrationDelegation: + return ( + + ); + case CertificateType.StakeVoteRegistrationDelegation: + return ( + + ); + case CertificateType.VoteRegistrationDelegation: + return ( + + ); + case CertificateType.RegisterDelegateRepresentative: + return ( + + ); + case CertificateType.UnregisterDelegateRepresentative: + return ( + + ); + case CertificateType.UpdateDelegateRepresentative: + return ( + + ); + case CertificateType.VoteDelegation: + return ( + + ); + case CertificateType.AuthorizeCommitteeHot: + return ( + + ); + case CertificateType.ResignCommitteeCold: + return ( + + ); + default: + throw new Error(`Not supported certificate: ${certificate.__typename}`); + } +}; diff --git a/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/TxDetailsCertificates.module.scss b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/TxDetailsCertificates.module.scss new file mode 100644 index 000000000..add3b802a --- /dev/null +++ b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/TxDetailsCertificates.module.scss @@ -0,0 +1,8 @@ +@import '../../../../styles/theme.scss'; +@import '../../../../../../../common/src/ui/styles/abstracts/typography'; + +.devider { + margin-top: 12px; + padding-top: 12px; + border-top: 1px solid var(--light-mode-light-grey-plus, var(--dark-mode-mid-grey)); +} \ No newline at end of file diff --git a/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/TxDetailsCertificates.tsx b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/TxDetailsCertificates.tsx new file mode 100644 index 000000000..f908400d1 --- /dev/null +++ b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsCertificates/TxDetailsCertificates.tsx @@ -0,0 +1,37 @@ +import { Wallet } from '@lace/cardano'; +import React from 'react'; +import { TxDetailsGroup } from '../../TxDetailsGroup'; +import { CertificateView } from './CertificateView'; +import { useTranslation } from 'react-i18next'; +import classNames from 'classnames'; +import { Box } from '@lace/ui'; +import styles from './TxDetailsCertificates.module.scss'; + +interface TxDetailsCertificatesProps { + chainNetworkId: Wallet.Cardano.NetworkId; + certificates: Wallet.Cardano.Certificate[]; + cardanoCoin: Wallet.CoinId; +} + +export const TxDetailsCertificates = ({ + certificates, + chainNetworkId, + cardanoCoin +}: TxDetailsCertificatesProps): React.ReactElement => { + const { t } = useTranslation(); + + return ( + + {certificates.map((cert, index) => ( + 0 + })} + key={`${cert.__typename}_${index}`} + > + + + ))} + + ); +}; diff --git a/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/ProposalProcedureAction.tsx b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/ProposalProcedureAction.tsx new file mode 100644 index 000000000..a7ed165e3 --- /dev/null +++ b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/ProposalProcedureAction.tsx @@ -0,0 +1,132 @@ +import { Wallet } from '@lace/cardano'; +import { + HardForkInitiationAction, + InfoAction, + NewConstitutionAction, + NoConfidenceAction, + ParameterChangeAction, + TreasuryWithdrawalsAction, + UpdateCommitteeAction +} from '@src/ui/components/ProposalProcedures'; +import { + getHardForkInitiationActionViewData, + getInfoActionViewData, + getNewConstitutionActionViewData, + getNoConfidenceActionViewData, + getParameterChangeActionViewData, + getTreasuryWithdrawalsActionViewData, + getUpdateCommitteeActionViewData +} from '@src/ui/utils'; +import React from 'react'; + +interface ProposalProcedureActionProps { + proposalProcedure: Wallet.Cardano.ProposalProcedure; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; +} + +export const ProposalProcedureAction = ({ + proposalProcedure: { deposit, rewardAccount, anchor, governanceAction }, + cardanoCoin, + explorerBaseUrl +}: ProposalProcedureActionProps): React.ReactElement => { + switch (governanceAction.__typename) { + case Wallet.Cardano.GovernanceActionType.parameter_change_action: + return ( + + ); + case Wallet.Cardano.GovernanceActionType.hard_fork_initiation_action: + return ( + + ); + + case Wallet.Cardano.GovernanceActionType.info_action: + return ( + + ); + case Wallet.Cardano.GovernanceActionType.new_constitution: + return ( + + ); + case Wallet.Cardano.GovernanceActionType.no_confidence: + return ( + + ); + case Wallet.Cardano.GovernanceActionType.treasury_withdrawals_action: + return ( + + ); + case Wallet.Cardano.GovernanceActionType.update_committee: + return ( + + ); + default: + throw new Error('unsupported governanceAction'); + } +}; diff --git a/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/TxDetailsProposalProcedures.tsx b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/TxDetailsProposalProcedures.tsx new file mode 100644 index 000000000..3007ea0af --- /dev/null +++ b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/TxDetailsProposalProcedures.tsx @@ -0,0 +1,34 @@ +import React from 'react'; +import { Wallet } from '@lace/cardano'; +import { useTranslation } from 'react-i18next'; +import { ProposalProcedureAction } from './ProposalProcedureAction'; +import { TxDetailsGroup } from '../../TxDetailsGroup'; + +interface TxDetailsProposalProceduresProps { + proposalProcedures: Wallet.Cardano.ProposalProcedure[]; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; +} + +export const TxDetailsProposalProcedures = ({ + proposalProcedures, + cardanoCoin, + explorerBaseUrl +}: TxDetailsProposalProceduresProps): React.ReactElement => { + const { t } = useTranslation(); + + return ( + + <> + {proposalProcedures.map((procedure) => ( + + ))} + + + ); +}; diff --git a/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/index.ts b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/index.ts new file mode 100644 index 000000000..42669d039 --- /dev/null +++ b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsProposalProcedures/index.ts @@ -0,0 +1 @@ +export { TxDetailsProposalProcedures } from './TxDetailsProposalProcedures'; diff --git a/packages/core/src/ui/components/ActivityDetail/components/TxDetailsVotingProcedures.tsx b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsVotingProcedures.tsx new file mode 100644 index 000000000..064bb642a --- /dev/null +++ b/packages/core/src/ui/components/ActivityDetail/components/TxDetailsVotingProcedures.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { Wallet } from '@lace/cardano'; +import { VotingProcedures } from '../../VotingProcedures'; +import { TxDetailsGroup } from '../TxDetailsGroup'; +import { useTranslation } from 'react-i18next'; + +interface TxDetailsVotingProceduresProps { + explorerBaseUrl: string; + votingProcedures: Wallet.Cardano.VotingProcedures; +} + +export const TxDetailsVotingProcedures = ({ + votingProcedures, + explorerBaseUrl +}: TxDetailsVotingProceduresProps): React.ReactElement => { + const { t } = useTranslation(); + + return ( + + + Wallet.util.mapVotingProcedureToView(votingProcedure, explorerBaseUrl) + )} + /> + + ); +}; diff --git a/packages/core/src/ui/components/ActivityDetail/components/index.ts b/packages/core/src/ui/components/ActivityDetail/components/index.ts deleted file mode 100644 index c470084f1..000000000 --- a/packages/core/src/ui/components/ActivityDetail/components/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './DetailRows'; diff --git a/packages/core/src/ui/components/AuthorizeCommitteeCertificate/AuthorizeCommitteeCertificate.tsx b/packages/core/src/ui/components/AuthorizeCommitteeCertificate/AuthorizeCommitteeCertificate.tsx new file mode 100644 index 000000000..9cddc67f3 --- /dev/null +++ b/packages/core/src/ui/components/AuthorizeCommitteeCertificate/AuthorizeCommitteeCertificate.tsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { Cell, Grid, TransactionSummary } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; + +interface Translations { + labels: { + hotCredential: string; + coldCredential: string; + }; +} +interface Props { + metadata: { + hotCredential: string; + coldCredential: string; + }; +} + +export const AuthorizeCommitteeCertificate = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + + const translations: Translations = { + labels: { + hotCredential: t('core.activityDetails.certificateTitles.hotCredential'), + coldCredential: t('core.activityDetails.certificateTitles.coldCredential') + } + }; + + return ( + + + + + + + + + + + + ); +}; diff --git a/packages/core/src/ui/components/AuthorizeCommitteeCertificate/index.ts b/packages/core/src/ui/components/AuthorizeCommitteeCertificate/index.ts new file mode 100644 index 000000000..0a26dff18 --- /dev/null +++ b/packages/core/src/ui/components/AuthorizeCommitteeCertificate/index.ts @@ -0,0 +1 @@ +export { AuthorizeCommitteeCertificate } from './AuthorizeCommitteeCertificate'; diff --git a/packages/core/src/ui/components/ConfirmDRepRegistration/ConfirmDRepRegistration.stories.tsx b/packages/core/src/ui/components/ConfirmDRepRegistration/ConfirmDRepRegistration.stories.tsx index cab80863c..99c00aa9e 100644 --- a/packages/core/src/ui/components/ConfirmDRepRegistration/ConfirmDRepRegistration.stories.tsx +++ b/packages/core/src/ui/components/ConfirmDRepRegistration/ConfirmDRepRegistration.stories.tsx @@ -29,20 +29,6 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, - translations: { - labels: { - depositPaid: 'Deposit paid', - drepId: 'DRep ID', - hash: 'Hash', - url: 'URL' - }, - metadata: 'Metadata' - }, metadata: { depositPaid: '0.35 ADA', drepId: '65ge6g54g5dd5', @@ -56,9 +42,3 @@ export const Overview: Story = { ...data } }; -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ConfirmDRepRegistration/ConfirmDRepRegistration.tsx b/packages/core/src/ui/components/ConfirmDRepRegistration/ConfirmDRepRegistration.tsx index 644b457fe..ea3e792ae 100644 --- a/packages/core/src/ui/components/ConfirmDRepRegistration/ConfirmDRepRegistration.tsx +++ b/packages/core/src/ui/components/ConfirmDRepRegistration/ConfirmDRepRegistration.tsx @@ -1,19 +1,16 @@ import React from 'react'; -import { Box, Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; -interface Props { - dappInfo: Omit; - errorMessage?: string; - translations: { - labels: { - url: string; - hash: string; - drepId: string; - depositPaid: string; - }; - metadata: string; +import { Cell, Grid, TransactionSummary } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; + +interface Translations { + labels: { + url: string; + hash: string; + drepId: string; + depositPaid: string; }; +} +interface Props { metadata: { url: string; hash: string; @@ -22,19 +19,26 @@ interface Props { }; } -export const ConfirmDRepRegistration = ({ dappInfo, errorMessage, translations, metadata }: Props): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} +export const ConfirmDRepRegistration = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + + const translations: Translations = { + labels: { + depositPaid: t('core.DRepRegistration.depositPaid'), + drepId: t('core.DRepRegistration.drepId'), + hash: t('core.DRepRegistration.hash'), + url: t('core.DRepRegistration.url') + } + }; + + return ( - + {metadata.url && ( @@ -61,5 +65,5 @@ export const ConfirmDRepRegistration = ({ dappInfo, errorMessage, translations, /> - -); + ); +}; diff --git a/packages/core/src/ui/components/ConfirmDRepRetirement/ConfirmDRepRetirement.stories.tsx b/packages/core/src/ui/components/ConfirmDRepRetirement/ConfirmDRepRetirement.stories.tsx index 9957bf2a9..99d354f0a 100644 --- a/packages/core/src/ui/components/ConfirmDRepRetirement/ConfirmDRepRetirement.stories.tsx +++ b/packages/core/src/ui/components/ConfirmDRepRetirement/ConfirmDRepRetirement.stories.tsx @@ -29,18 +29,6 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, - translations: { - labels: { - depositReturned: 'Deposit paid', - drepId: 'DRep ID' - }, - metadata: 'Metadata' - }, metadata: { depositReturned: '0.35 ADA', drepId: '65ge6g54g5dd5' @@ -52,9 +40,3 @@ export const Overview: Story = { ...data } }; -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ConfirmDRepRetirement/ConfirmDRepRetirement.tsx b/packages/core/src/ui/components/ConfirmDRepRetirement/ConfirmDRepRetirement.tsx index 59219813a..b51b34523 100644 --- a/packages/core/src/ui/components/ConfirmDRepRetirement/ConfirmDRepRetirement.tsx +++ b/packages/core/src/ui/components/ConfirmDRepRetirement/ConfirmDRepRetirement.tsx @@ -1,37 +1,32 @@ import React from 'react'; -import { Box, Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Cell, Grid, TransactionSummary } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; interface Props { - dappInfo: Omit; - errorMessage?: string; - translations: { - labels: { - drepId: string; - depositReturned: string; - }; - metadata: string; - }; metadata: { drepId: string; depositReturned: string; }; } -export const ConfirmDRepRetirement = ({ dappInfo, errorMessage, translations, metadata }: Props): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} +export const ConfirmDRepRetirement = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + + const translations = { + labels: { + depositReturned: t('core.DRepRetirement.depositReturned'), + drepId: t('core.DRepRetirement.drepId') + } + }; + + return ( - + - -); + ); +}; diff --git a/packages/core/src/ui/components/ConfirmDRepUpdate/ConfirmDRepUpdate.stories.tsx b/packages/core/src/ui/components/ConfirmDRepUpdate/ConfirmDRepUpdate.stories.tsx index 2d136f641..436efbf83 100644 --- a/packages/core/src/ui/components/ConfirmDRepUpdate/ConfirmDRepUpdate.stories.tsx +++ b/packages/core/src/ui/components/ConfirmDRepUpdate/ConfirmDRepUpdate.stories.tsx @@ -29,19 +29,6 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, - translations: { - labels: { - drepId: 'DRep ID', - hash: 'Hash', - url: 'URL' - }, - metadata: 'Metadata' - }, metadata: { drepId: '65ge6g54g5dd5', hash: '9bba8233cdd086f0325daba465d568a88970d42536f9e71e92a80d5922ded885', @@ -63,10 +50,3 @@ export const Empty: Story = { } } }; - -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ConfirmDRepUpdate/ConfirmDRepUpdate.tsx b/packages/core/src/ui/components/ConfirmDRepUpdate/ConfirmDRepUpdate.tsx index e86ee2b77..20d1961e6 100644 --- a/packages/core/src/ui/components/ConfirmDRepUpdate/ConfirmDRepUpdate.tsx +++ b/packages/core/src/ui/components/ConfirmDRepUpdate/ConfirmDRepUpdate.tsx @@ -1,19 +1,8 @@ import React from 'react'; -import { Box, Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Cell, Grid, TransactionSummary } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; interface Props { - dappInfo: Omit; - errorMessage?: string; - translations: { - labels: { - url: string; - hash: string; - drepId: string; - }; - metadata: string; - }; metadata: { url?: string; hash?: string; @@ -21,19 +10,26 @@ interface Props { }; } -export const ConfirmDRepUpdate = ({ dappInfo, errorMessage, translations, metadata }: Props): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} +export const ConfirmDRepUpdate = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + + const translations = { + metadata: t('core.DRepUpdate.metadata'), + labels: { + drepId: t('core.DRepUpdate.drepId'), + hash: t('core.DRepUpdate.hash'), + url: t('core.DRepUpdate.url') + } + }; + + return ( - + {metadata.url && ( @@ -53,5 +49,5 @@ export const ConfirmDRepUpdate = ({ dappInfo, errorMessage, translations, metada /> - -); + ); +}; diff --git a/packages/core/src/ui/components/ConfirmStakeRegistrationDelegation/ConfirmStakeRegistrationDelegation.stories.tsx b/packages/core/src/ui/components/ConfirmStakeRegistrationDelegation/ConfirmStakeRegistrationDelegation.stories.tsx index 86c53affd..6c307f1fb 100644 --- a/packages/core/src/ui/components/ConfirmStakeRegistrationDelegation/ConfirmStakeRegistrationDelegation.stories.tsx +++ b/packages/core/src/ui/components/ConfirmStakeRegistrationDelegation/ConfirmStakeRegistrationDelegation.stories.tsx @@ -29,19 +29,6 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, - translations: { - labels: { - stakeKeyHash: 'Stake key hash', - poolId: 'Pool Id', - depositPaid: 'Deposit paid' - }, - metadata: 'Metadata' - }, metadata: { stakeKeyHash: '13cf55d175ea848b87deb3e914febd7e028e2bf6534475d52fb9c3d0', poolId: 'pool1zuevzm3xlrhmwjw87ec38mzs02tlkwec9wxpgafcaykmwg7efhh', @@ -54,9 +41,3 @@ export const Overview: Story = { ...data } }; -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ConfirmStakeRegistrationDelegation/ConfirmStakeRegistrationDelegation.tsx b/packages/core/src/ui/components/ConfirmStakeRegistrationDelegation/ConfirmStakeRegistrationDelegation.tsx index ada22bfaf..84ee2c30b 100644 --- a/packages/core/src/ui/components/ConfirmStakeRegistrationDelegation/ConfirmStakeRegistrationDelegation.tsx +++ b/packages/core/src/ui/components/ConfirmStakeRegistrationDelegation/ConfirmStakeRegistrationDelegation.tsx @@ -1,19 +1,8 @@ import React from 'react'; -import { Box, Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; interface Props { - dappInfo: Omit; - errorMessage?: string; - translations: { - labels: { - poolId: string; - stakeKeyHash: string; - depositPaid: string; - }; - metadata: string; - }; metadata: { poolId: string; stakeKeyHash: string; @@ -21,34 +10,36 @@ interface Props { }; } -export const ConfirmStakeRegistrationDelegation = ({ - dappInfo, - errorMessage, - translations, - metadata -}: Props): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} - - - - - - - - - - - - - - - -); +export const ConfirmStakeRegistrationDelegation = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + const translations = { + labels: { + poolId: t('core.StakeRegistrationDelegation.poolId'), + stakeKeyHash: t('core.StakeRegistrationDelegation.stakeKeyHash'), + depositPaid: t('core.StakeRegistrationDelegation.depositPaid') + } + }; + + return ( + + + + + + + + + + + + + + + + + ); +}; diff --git a/packages/core/src/ui/components/ConfirmStakeVoteDelegation/ConfirmStakeVoteDelegation.stories.tsx b/packages/core/src/ui/components/ConfirmStakeVoteDelegation/ConfirmStakeVoteDelegation.stories.tsx index 0693e3c81..c88b0c83d 100644 --- a/packages/core/src/ui/components/ConfirmStakeVoteDelegation/ConfirmStakeVoteDelegation.stories.tsx +++ b/packages/core/src/ui/components/ConfirmStakeVoteDelegation/ConfirmStakeVoteDelegation.stories.tsx @@ -29,22 +29,6 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, - translations: { - labels: { - drepId: 'DRep ID', - alwaysAbstain: 'Abstain', - alwaysNoConfidence: 'No Confidence', - stakeKeyHash: 'Stake key hash', - poolId: 'Pool Id' - }, - option: 'Yes', - metadata: 'Metadata' - }, metadata: { drepId: 'drep1ruvgm0auzdplfn7g2jf3kcnpnw5mlhwxaxj8crag8h6t2ye9y9g', alwaysAbstain: false, @@ -59,12 +43,6 @@ export const Overview: Story = { ...data } }; -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; export const WithAbstain: Story = { args: { diff --git a/packages/core/src/ui/components/ConfirmStakeVoteDelegation/ConfirmStakeVoteDelegation.tsx b/packages/core/src/ui/components/ConfirmStakeVoteDelegation/ConfirmStakeVoteDelegation.tsx index 77cfd3243..37caa3792 100644 --- a/packages/core/src/ui/components/ConfirmStakeVoteDelegation/ConfirmStakeVoteDelegation.tsx +++ b/packages/core/src/ui/components/ConfirmStakeVoteDelegation/ConfirmStakeVoteDelegation.tsx @@ -1,22 +1,8 @@ import React from 'react'; -import { Box, Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; interface Props { - dappInfo: Omit; - errorMessage?: string; - translations: { - labels: { - poolId: string; - stakeKeyHash: string; - drepId: string; - alwaysAbstain: string; - alwaysNoConfidence: string; - }; - option: string; - metadata: string; - }; metadata: { poolId: string; stakeKeyHash: string; @@ -26,41 +12,52 @@ interface Props { }; } -export const ConfirmStakeVoteDelegation = ({ dappInfo, errorMessage, translations, metadata }: Props): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} - - - - - {metadata.drepId && ( +export const ConfirmStakeVoteDelegation = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + + const translations = { + option: t('core.StakeVoteDelegation.option'), + labels: { + poolId: t('core.StakeVoteDelegation.poolId'), + stakeKeyHash: t('core.StakeVoteDelegation.stakeKeyHash'), + drepId: t('core.StakeVoteDelegation.drepId'), + alwaysAbstain: t('core.StakeVoteDelegation.alwaysAbstain'), + alwaysNoConfidence: t('core.StakeVoteDelegation.alwaysNoConfidence') + } + }; + + return ( + + - + - )} - {metadata.alwaysAbstain && ( + {metadata.drepId && ( + + + + )} + {metadata.alwaysAbstain && ( + + + + )} + {metadata.alwaysNoConfidence && ( + + + + )} - + - )} - {metadata.alwaysNoConfidence && ( - + - )} - - - - - - - - -); + + + ); +}; diff --git a/packages/core/src/ui/components/ConfirmStakeVoteRegistrationDelegation/ConfirmStakeVoteRegistrationDelegation.stories.tsx b/packages/core/src/ui/components/ConfirmStakeVoteRegistrationDelegation/ConfirmStakeVoteRegistrationDelegation.stories.tsx index 309d840eb..075c105c7 100644 --- a/packages/core/src/ui/components/ConfirmStakeVoteRegistrationDelegation/ConfirmStakeVoteRegistrationDelegation.stories.tsx +++ b/packages/core/src/ui/components/ConfirmStakeVoteRegistrationDelegation/ConfirmStakeVoteRegistrationDelegation.stories.tsx @@ -29,23 +29,6 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, - translations: { - labels: { - drepId: 'DRep ID', - alwaysAbstain: 'Abstain', - alwaysNoConfidence: 'No Confidence', - stakeKeyHash: 'Stake key hash', - poolId: 'Pool Id', - depositPaid: 'Deposit paid' - }, - option: 'Yes', - metadata: 'Metadata' - }, metadata: { drepId: 'drep1ruvgm0auzdplfn7g2jf3kcnpnw5mlhwxaxj8crag8h6t2ye9y9g', alwaysAbstain: false, @@ -61,12 +44,6 @@ export const Overview: Story = { ...data } }; -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; export const WithAbstain: Story = { args: { diff --git a/packages/core/src/ui/components/ConfirmStakeVoteRegistrationDelegation/ConfirmStakeVoteRegistrationDelegation.tsx b/packages/core/src/ui/components/ConfirmStakeVoteRegistrationDelegation/ConfirmStakeVoteRegistrationDelegation.tsx index a8e0789e4..07216d68c 100644 --- a/packages/core/src/ui/components/ConfirmStakeVoteRegistrationDelegation/ConfirmStakeVoteRegistrationDelegation.tsx +++ b/packages/core/src/ui/components/ConfirmStakeVoteRegistrationDelegation/ConfirmStakeVoteRegistrationDelegation.tsx @@ -1,23 +1,8 @@ import React from 'react'; -import { Box, Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; interface Props { - dappInfo: Omit; - errorMessage?: string; - translations: { - labels: { - poolId: string; - stakeKeyHash: string; - drepId: string; - alwaysAbstain: string; - alwaysNoConfidence: string; - depositPaid: string; - }; - option: string; - metadata: string; - }; metadata: { poolId: string; stakeKeyHash: string; @@ -28,49 +13,56 @@ interface Props { }; } -export const ConfirmStakeVoteRegistrationDelegation = ({ - dappInfo, - errorMessage, - translations, - metadata -}: Props): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} - - - - - {metadata.drepId && ( +export const ConfirmStakeVoteRegistrationDelegation = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + + const translations = { + option: t('core.StakeVoteDelegationRegistration.option'), + labels: { + poolId: t('core.StakeVoteDelegationRegistration.poolId'), + stakeKeyHash: t('core.StakeVoteDelegationRegistration.stakeKeyHash'), + drepId: t('core.StakeVoteDelegationRegistration.drepId'), + alwaysAbstain: t('core.StakeVoteDelegationRegistration.alwaysAbstain'), + alwaysNoConfidence: t('core.StakeVoteDelegationRegistration.alwaysNoConfidence'), + depositPaid: t('core.StakeVoteDelegationRegistration.depositPaid') + } + }; + + return ( + + + + + + {metadata.drepId && ( + + + + )} + {metadata.alwaysAbstain && ( + + + + )} + {metadata.alwaysNoConfidence && ( + + + + )} - + - )} - {metadata.alwaysAbstain && ( - + - )} - {metadata.alwaysNoConfidence && ( - + - )} - - - - - - - - - - - -); + + + ); +}; diff --git a/packages/core/src/ui/components/ConfirmVoteDelegation/ConfirmVoteDelegation.stories.tsx b/packages/core/src/ui/components/ConfirmVoteDelegation/ConfirmVoteDelegation.stories.tsx index 2b0f7d96a..a9595d5b4 100644 --- a/packages/core/src/ui/components/ConfirmVoteDelegation/ConfirmVoteDelegation.stories.tsx +++ b/packages/core/src/ui/components/ConfirmVoteDelegation/ConfirmVoteDelegation.stories.tsx @@ -29,20 +29,6 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, - translations: { - labels: { - drepId: 'DRep ID', - alwaysAbstain: 'Abstain', - alwaysNoConfidence: 'No Confidence' - }, - option: 'Yes', - metadata: 'Metadata' - }, metadata: { drepId: 'drep1ruvgm0auzdplfn7g2jf3kcnpnw5mlhwxaxj8crag8h6t2ye9y9g', alwaysAbstain: false, @@ -55,12 +41,6 @@ export const Overview: Story = { ...data } }; -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; export const WithAbstain: Story = { args: { diff --git a/packages/core/src/ui/components/ConfirmVoteDelegation/ConfirmVoteDelegation.tsx b/packages/core/src/ui/components/ConfirmVoteDelegation/ConfirmVoteDelegation.tsx index 4eae2a274..fc013e785 100644 --- a/packages/core/src/ui/components/ConfirmVoteDelegation/ConfirmVoteDelegation.tsx +++ b/packages/core/src/ui/components/ConfirmVoteDelegation/ConfirmVoteDelegation.tsx @@ -1,20 +1,8 @@ import React from 'react'; -import { Box, Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Cell, Grid, TransactionSummary } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; interface Props { - dappInfo: Omit; - errorMessage?: string; - translations: { - labels: { - drepId: string; - alwaysAbstain: string; - alwaysNoConfidence: string; - }; - option: string; - metadata: string; - }; metadata: { drepId?: string; alwaysAbstain: boolean; @@ -22,19 +10,26 @@ interface Props { }; } -export const ConfirmVoteDelegation = ({ dappInfo, errorMessage, translations, metadata }: Props): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} +export const ConfirmVoteDelegation = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + const translations = { + metadata: t('core.VoteDelegation.metadata'), + option: t('core.VoteDelegation.option'), + labels: { + drepId: t('core.VoteDelegation.drepId'), + alwaysAbstain: t('core.VoteDelegation.alwaysAbstain'), + alwaysNoConfidence: t('core.VoteDelegation.alwaysNoConfidence') + } + }; + + return ( - + {metadata.drepId && ( @@ -64,5 +59,5 @@ export const ConfirmVoteDelegation = ({ dappInfo, errorMessage, translations, me )} - -); + ); +}; diff --git a/packages/core/src/ui/components/ConfirmVoteRegistrationDelegation/ConfirmVoteRegistrationDelegation.stories.tsx b/packages/core/src/ui/components/ConfirmVoteRegistrationDelegation/ConfirmVoteRegistrationDelegation.stories.tsx index c6ece5b76..d7fad93ad 100644 --- a/packages/core/src/ui/components/ConfirmVoteRegistrationDelegation/ConfirmVoteRegistrationDelegation.stories.tsx +++ b/packages/core/src/ui/components/ConfirmVoteRegistrationDelegation/ConfirmVoteRegistrationDelegation.stories.tsx @@ -29,22 +29,6 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, - translations: { - labels: { - drepId: 'DRep ID', - alwaysAbstain: 'Abstain', - alwaysNoConfidence: 'No Confidence', - depositPaid: 'Deposit paid', - stakeKeyHash: 'Stake key hash' - }, - option: 'Yes', - metadata: 'Metadata' - }, metadata: { drepId: 'drep1ruvgm0auzdplfn7g2jf3kcnpnw5mlhwxaxj8crag8h6t2ye9y9g', alwaysAbstain: false, @@ -59,12 +43,6 @@ export const Overview: Story = { ...data } }; -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; export const WithAbstain: Story = { args: { diff --git a/packages/core/src/ui/components/ConfirmVoteRegistrationDelegation/ConfirmVoteRegistrationDelegation.tsx b/packages/core/src/ui/components/ConfirmVoteRegistrationDelegation/ConfirmVoteRegistrationDelegation.tsx index 39f184e26..8fe46c5a3 100644 --- a/packages/core/src/ui/components/ConfirmVoteRegistrationDelegation/ConfirmVoteRegistrationDelegation.tsx +++ b/packages/core/src/ui/components/ConfirmVoteRegistrationDelegation/ConfirmVoteRegistrationDelegation.tsx @@ -1,22 +1,8 @@ import React from 'react'; -import { Box, Cell, Grid, TransactionSummary, Flex } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Cell, Grid, TransactionSummary } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; interface Props { - dappInfo: Omit; - errorMessage?: string; - translations: { - labels: { - drepId: string; - alwaysAbstain: string; - alwaysNoConfidence: string; - stakeKeyHash: string; - depositPaid: string; - }; - option: string; - metadata: string; - }; metadata: { drepId?: string; alwaysAbstain: boolean; @@ -26,24 +12,27 @@ interface Props { }; } -export const ConfirmVoteRegistrationDelegation = ({ - dappInfo, - errorMessage, - translations, - metadata -}: Props): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} +export const ConfirmVoteRegistrationDelegation = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + const translations = { + option: t('core.VoteRegistrationDelegation.option'), + labels: { + drepId: t('core.VoteRegistrationDelegation.drepId'), + alwaysAbstain: t('core.VoteRegistrationDelegation.alwaysAbstain'), + alwaysNoConfidence: t('core.VoteRegistrationDelegation.alwaysNoConfidence'), + depositPaid: t('core.VoteRegistrationDelegation.depositPaid'), + stakeKeyHash: t('core.VoteRegistrationDelegation.stakeKeyHash') + } + }; + + return ( - + {metadata.drepId && ( @@ -67,5 +56,5 @@ export const ConfirmVoteRegistrationDelegation = ({ - -); + ); +}; diff --git a/packages/core/src/ui/components/DappTransaction/DappTransaction.tsx b/packages/core/src/ui/components/DappTransaction/DappTransaction.tsx index 4888f7986..2a5757ef0 100644 --- a/packages/core/src/ui/components/DappTransaction/DappTransaction.tsx +++ b/packages/core/src/ui/components/DappTransaction/DappTransaction.tsx @@ -86,17 +86,8 @@ const groupAddresses = (addresses: Map | { [Symbol.toPrimitive](hint: 'string'): string } -): string => { - const bytes = Uint8Array.from(Buffer.from(value, 'hex')); - const decoder = new TextDecoder('utf-8'); - // Decode the Uint8Array to a UTF-8 string - return decoder.decode(bytes); -}; - const getFallbackName = (asset: AssetInfoWithAmount) => - tryDecodeAsUtf8(asset.assetInfo.name) ? tryDecodeAsUtf8(asset.assetInfo.name) : asset.assetInfo.assetId; + Wallet.Cardano.AssetName.toUTF8(asset.assetInfo.name) || asset.assetInfo.assetId; const getAssetTokenName = (assetWithAmount: AssetInfoWithAmount) => { if (isNFT(assetWithAmount)) { diff --git a/packages/core/src/ui/components/Nft/NftDetail.tsx b/packages/core/src/ui/components/Nft/NftDetail.tsx index 1b8957a56..8ad348aed 100644 --- a/packages/core/src/ui/components/Nft/NftDetail.tsx +++ b/packages/core/src/ui/components/Nft/NftDetail.tsx @@ -58,6 +58,7 @@ export const NftDetail = ({ label={translations.setAsAvatar} icon={} onClick={() => onSetAsAvatar(image)} + data-testid="nft-set-as-avatar-button" />
diff --git a/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationAction.stories.tsx b/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationAction.stories.tsx index 61c09528c..ad069f724 100644 --- a/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationAction.stories.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationAction.stories.tsx @@ -29,14 +29,8 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, data: { txDetails: { - txType: 'Hard Fork Initiation', deposit: '2000', rewardAccount: 'stake1u89sasnfyjtmgk8ydqfv3fdl52f36x3djedfnzfc9rkgzrcss5vgr' }, @@ -56,31 +50,6 @@ const data: ComponentProps = { minor: '1', patch: '1' } - }, - translations: { - txDetails: { - title: 'Transaction Details', - txType: 'Transaction Type', - deposit: 'Deposit', - rewardAccount: 'Reward Account' - }, - procedure: { - anchor: { - hash: 'Anchor Hash', - url: 'Anchor URL' - }, - title: 'Procedure' - }, - actionId: { - title: 'Action ID', - index: 'Index', - txId: 'TX ID' - }, - protocolVersion: { - major: 'Protocol Version Major', - minor: 'Protocol Version Minor', - patch: 'Protocol Version Patch' - } } }; @@ -89,10 +58,3 @@ export const Overview: Story = { ...data } }; - -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationAction.tsx b/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationAction.tsx index 6a722f101..1971ca339 100644 --- a/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationAction.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationAction.tsx @@ -1,37 +1,54 @@ import React from 'react'; -import { Box, Grid, Flex, Divider, Metadata, Cell } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Grid, Divider, Metadata, Cell } from '@lace/ui'; import * as Types from './HardForkInitiationActionTypes'; -import { TransactionDetails } from '../components/TransactionDetails'; +import { ProposalProcedureTransactionDetails } from '../components/ProposalProcedureTransactionDetails'; import { Procedure } from '../components/Procedure'; import { ActionId } from '../components/ActionId'; +import { useTranslation } from 'react-i18next'; export interface HardForkInitiationActionProps { - dappInfo: Omit; - errorMessage?: string; data: Types.Data; - translations: Types.Translations; } export const HardForkInitiationAction = ({ - dappInfo, - errorMessage, - data: { procedure, txDetails, actionId, protocolVersion }, - translations -}: HardForkInitiationActionProps): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} + data: { procedure, txDetails, actionId, protocolVersion } +}: HardForkInitiationActionProps): JSX.Element => { + const { t } = useTranslation(); + const translations: Types.Translations = { + txDetails: { + title: t('core.ProposalProcedure.txDetails.title'), + txType: t('core.ProposalProcedure.txDetails.txType'), + deposit: t('core.ProposalProcedure.txDetails.deposit'), + rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') + }, + procedure: { + title: t('core.ProposalProcedure.procedure.title'), + anchor: { + url: t('core.ProposalProcedure.procedure.anchor.url'), + hash: t('core.ProposalProcedure.procedure.anchor.hash') + } + }, + protocolVersion: { + major: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.major'), + minor: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.minor'), + patch: t('core.ProposalProcedure.governanceAction.hardForkInitiation.protocolVersion.patch') + }, + actionId: { + title: t('core.ProposalProcedure.governanceAction.actionId.title'), + index: t('core.ProposalProcedure.governanceAction.actionId.index'), + txId: t('core.ProposalProcedure.governanceAction.actionId.txId') + } + }; + + return ( {/* tx details section */} - + @@ -58,5 +75,5 @@ export const HardForkInitiationAction = ({ )} - -); + ); +}; diff --git a/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationActionTypes.ts b/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationActionTypes.ts index bd8ae61b7..1ca635e5f 100644 --- a/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationActionTypes.ts +++ b/packages/core/src/ui/components/ProposalProcedures/HardForkInitiationAction/HardForkInitiationActionTypes.ts @@ -1,6 +1,6 @@ import * as ProcedureTypes from '../components/ProcedureTypes'; import * as ActionIdTypes from '../components/ActionIdTypes'; -import * as TxDetailsTypes from '../components/TransactionDetailsTypes'; +import * as TxDetailsTypes from '../components/ProposalProcedureTransactionDetailsTypes'; export interface Data { txDetails: TxDetailsTypes.TxDetails; diff --git a/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoAction.stories.tsx b/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoAction.stories.tsx index 2dd07ef93..0edbb489a 100644 --- a/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoAction.stories.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoAction.stories.tsx @@ -29,15 +29,8 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, data: { - txDetails: { - txType: 'Info action' - }, + txDetails: {}, procedure: { anchor: { hash: '26bfdcc75a7f4d0cd8c71f0189bc5ca5ad2f4a3db6240c82b5a0edac7f9203e0', @@ -45,19 +38,6 @@ const data: ComponentProps = { txHashUrl: 'https://www.someurl.io' } } - }, - translations: { - txDetails: { - title: 'Transaction Details', - txType: 'Transaction Type' - }, - procedure: { - anchor: { - hash: 'Anchor Hash', - url: 'Anchor URL' - }, - title: 'Procedure' - } } }; @@ -66,10 +46,3 @@ export const Overview: Story = { ...data } }; - -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoAction.tsx b/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoAction.tsx index b84260bd9..bea0b2cb6 100644 --- a/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoAction.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoAction.tsx @@ -1,40 +1,45 @@ -import React from 'react'; -import { Box, Grid, Flex, Divider, Cell } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../../DappInfo'; -import { ErrorPane } from '@lace/common'; +import React, { useMemo } from 'react'; +import { Grid, Divider, Cell } from '@lace/ui'; import * as Types from './InfoActionTypes'; -import { TransactionDetails } from '../components/TransactionDetails'; +import { ProposalProcedureTransactionDetails } from '../components/ProposalProcedureTransactionDetails'; import { Procedure } from '../components/Procedure'; +import { useTranslation } from 'react-i18next'; export interface InfoActionProps { - dappInfo: Omit; - errorMessage?: string; data: Types.Data; - translations: Types.Translations; } -export const InfoAction = ({ - dappInfo, - errorMessage, - data: { procedure, txDetails }, - translations -}: InfoActionProps): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} +export const InfoAction = ({ data: { procedure, txDetails } }: InfoActionProps): JSX.Element => { + const { t } = useTranslation(); + const translations = useMemo( + () => ({ + txDetails: { + title: t('core.ProposalProcedure.txDetails.title'), + txType: t('core.ProposalProcedure.txDetails.txType') + }, + procedure: { + title: t('core.ProposalProcedure.procedure.title'), + anchor: { + url: t('core.ProposalProcedure.procedure.anchor.url'), + hash: t('core.ProposalProcedure.procedure.anchor.hash') + } + } + }), + [t] + ); + return ( - + {/* procedure section */} - -); + ); +}; diff --git a/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoActionTypes.ts b/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoActionTypes.ts index 2f8853991..1006df470 100644 --- a/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoActionTypes.ts +++ b/packages/core/src/ui/components/ProposalProcedures/InfoAction/InfoActionTypes.ts @@ -1,5 +1,5 @@ import * as ProcedureTypes from '../components/ProcedureTypes'; -import * as TxDetailsTypes from '../components/TransactionDetailsTypes'; +import * as TxDetailsTypes from '../components/ProposalProcedureTransactionDetailsTypes'; export interface Data { txDetails: TxDetailsTypes.TxDetails; procedure: ProcedureTypes.Procedure; diff --git a/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionAction.stories.tsx b/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionAction.stories.tsx index b5ac821cc..6c426c16d 100644 --- a/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionAction.stories.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionAction.stories.tsx @@ -29,14 +29,8 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, data: { txDetails: { - txType: 'New Constitution', deposit: '2000', rewardAccount: 'stake1u89sasnfyjtmgk8ydqfv3fdl52f36x3djedfnzfc9rkgzrcss5vgr' }, @@ -58,34 +52,6 @@ const data: ComponentProps = { }, scriptHash: 'cb0ec2692497b458e46812c8a5bfa2931d1a2d965a99893828ec810f' } - }, - translations: { - txDetails: { - title: 'Transaction Details', - txType: 'Transaction Type', - deposit: 'Deposit', - rewardAccount: 'Reward Account' - }, - procedure: { - anchor: { - hash: 'Anchor Hash', - url: 'Anchor URL' - }, - title: 'Procedure' - }, - actionId: { - title: 'Action ID', - index: 'Index', - txId: 'TX ID' - }, - constitution: { - title: 'Constitution Details', - anchor: { - dataHash: 'Anchor Data Hash', - url: 'Anchor URL' - }, - scriptHash: 'Script Hash' - } } }; @@ -94,10 +60,3 @@ export const Overview: Story = { ...data } }; - -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionAction.tsx b/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionAction.tsx index 7fb710ab0..e4f684582 100644 --- a/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionAction.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionAction.tsx @@ -1,37 +1,59 @@ -import React from 'react'; -import { Box, Grid, Flex, Divider, Metadata, MetadataLink, Cell } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../../DappInfo'; -import { ErrorPane } from '@lace/common'; +import React, { useMemo } from 'react'; +import { Grid, Divider, Metadata, MetadataLink, Cell } from '@lace/ui'; import * as Types from './NewConstitutionActionTypes'; -import { TransactionDetails } from '../components/TransactionDetails'; +import { ProposalProcedureTransactionDetails } from '../components/ProposalProcedureTransactionDetails'; import { Procedure } from '../components/Procedure'; import { ActionId } from '../components/ActionId'; - +import { useTranslation } from 'react-i18next'; export interface NewConstitutionActionProps { - dappInfo: Omit; - errorMessage?: string; data: Types.Data; - translations: Types.Translations; } export const NewConstitutionAction = ({ - dappInfo, - errorMessage, - data: { txDetails, procedure, constitution, actionId }, - translations -}: NewConstitutionActionProps): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} + data: { txDetails, procedure, constitution, actionId } +}: NewConstitutionActionProps): JSX.Element => { + const { t } = useTranslation(); + const translations = useMemo( + () => ({ + txDetails: { + title: t('core.ProposalProcedure.txDetails.title'), + txType: t('core.ProposalProcedure.txDetails.txType'), + deposit: t('core.ProposalProcedure.txDetails.deposit'), + rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') + }, + procedure: { + title: t('core.ProposalProcedure.procedure.title'), + anchor: { + url: t('core.ProposalProcedure.procedure.anchor.url'), + hash: t('core.ProposalProcedure.procedure.anchor.hash') + } + }, + constitution: { + title: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.title'), + anchor: { + dataHash: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.anchor.dataHash'), + url: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.anchor.url') + }, + scriptHash: t('core.ProposalProcedure.governanceAction.newConstitutionAction.constitution.scriptHash') + }, + actionId: { + title: t('core.ProposalProcedure.governanceAction.actionId.title'), + index: t('core.ProposalProcedure.governanceAction.actionId.index'), + txId: t('core.ProposalProcedure.governanceAction.actionId.txId') + } + }), + [t] + ); + + return ( {/* txDetails section */} - + @@ -59,5 +81,5 @@ export const NewConstitutionAction = ({ )} - -); + ); +}; diff --git a/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionActionTypes.ts b/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionActionTypes.ts index 4d53001a2..23dbd5089 100644 --- a/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionActionTypes.ts +++ b/packages/core/src/ui/components/ProposalProcedures/NewConstitutionAction/NewConstitutionActionTypes.ts @@ -1,6 +1,6 @@ import * as ProcedureTypes from '../components/ProcedureTypes'; import * as ActionIdTypes from '../components/ActionIdTypes'; -import * as TxDetailsTypes from '../components/TransactionDetailsTypes'; +import * as TxDetailsTypes from '../components/ProposalProcedureTransactionDetailsTypes'; export interface Data { procedure: ProcedureTypes.Procedure; diff --git a/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceAction.stories.tsx b/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceAction.stories.tsx index 916673236..90c469e48 100644 --- a/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceAction.stories.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceAction.stories.tsx @@ -29,14 +29,8 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, data: { txDetails: { - txType: 'No Confidence', deposit: '2000', rewardAccount: 'stake1u89sasnfyjtmgk8ydqfv3fdl52f36x3djedfnzfc9rkgzrcss5vgr' }, @@ -51,26 +45,6 @@ const data: ComponentProps = { index: '0', id: '26bfdcc75a7f4d0cd8c71f0189bc5ca5ad2f4a3db6240c82b5a0edac7f9203e0' } - }, - translations: { - txDetails: { - title: 'Transaction Details', - txType: 'Transaction Type', - deposit: 'Deposit', - rewardAccount: 'Reward Account' - }, - procedure: { - anchor: { - hash: 'Anchor Hash', - url: 'Anchor URL' - }, - title: 'Procedure' - }, - actionId: { - title: 'Action ID', - index: 'Index', - txId: 'TX ID' - } } }; @@ -79,10 +53,3 @@ export const Overview: Story = { ...data } }; - -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceAction.tsx b/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceAction.tsx index 73034a6fe..c23284377 100644 --- a/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceAction.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceAction.tsx @@ -1,37 +1,53 @@ -import React from 'react'; -import { Box, Grid, Flex, Divider, Cell } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../../DappInfo'; -import { ErrorPane } from '@lace/common'; +import React, { useMemo } from 'react'; +import { Grid, Divider, Cell } from '@lace/ui'; import * as Types from './NoConfidenceActionTypes'; -import { TransactionDetails } from '../components/TransactionDetails'; +import { ProposalProcedureTransactionDetails } from '../components/ProposalProcedureTransactionDetails'; import { Procedure } from '../components/Procedure'; import { ActionId } from '../components/ActionId'; +import { useTranslation } from 'react-i18next'; export interface NoConfidenceActionProps { - dappInfo: Omit; - errorMessage?: string; data: Types.Data; - translations: Types.Translations; } export const NoConfidenceAction = ({ - dappInfo, - errorMessage, - data: { procedure, txDetails, actionId }, - translations -}: NoConfidenceActionProps): JSX.Element => ( - - - - - {errorMessage && ( - - - - )} + data: { procedure, txDetails, actionId } +}: NoConfidenceActionProps): JSX.Element => { + const { t } = useTranslation(); + + const translations = useMemo( + () => ({ + txDetails: { + title: t('core.ProposalProcedure.txDetails.title'), + txType: t('core.ProposalProcedure.txDetails.txType'), + deposit: t('core.ProposalProcedure.txDetails.deposit'), + rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') + }, + procedure: { + title: t('core.ProposalProcedure.procedure.title'), + anchor: { + url: t('core.ProposalProcedure.procedure.anchor.url'), + hash: t('core.ProposalProcedure.procedure.anchor.hash') + } + }, + actionId: { + title: t('core.ProposalProcedure.governanceAction.actionId.title'), + index: t('core.ProposalProcedure.governanceAction.actionId.index'), + txId: t('core.ProposalProcedure.governanceAction.actionId.txId') + } + }), + [t] + ); + + return ( {/* tx details section */} - + @@ -47,5 +63,5 @@ export const NoConfidenceAction = ({ )} - -); + ); +}; diff --git a/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceActionTypes.ts b/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceActionTypes.ts index 0cdfcea7d..c71fd5dca 100644 --- a/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceActionTypes.ts +++ b/packages/core/src/ui/components/ProposalProcedures/NoConfidenceAction/NoConfidenceActionTypes.ts @@ -1,6 +1,6 @@ import * as ProcedureTypes from '../components/ProcedureTypes'; import * as ActionIdTypes from '../components/ActionIdTypes'; -import * as TxDetailsTypes from '../components/TransactionDetailsTypes'; +import * as TxDetailsTypes from '../components/ProposalProcedureTransactionDetailsTypes'; export interface Data { procedure: ProcedureTypes.Procedure; diff --git a/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeAction.stories.tsx b/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeAction.stories.tsx index 45ffa160b..b6ed3bb67 100644 --- a/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeAction.stories.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeAction.stories.tsx @@ -29,14 +29,8 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, data: { txDetails: { - txType: 'Protocol Parameter Update', deposit: '2000', rewardAccount: 'stake1u89sasnfyjtmgk8ydqfv3fdl52f36x3djedfnzfc9rkgzrcss5vgr' }, @@ -112,120 +106,6 @@ const data: ComponentProps = { } } } - }, - translations: { - txDetails: { - title: 'Transaction Details', - txType: 'Transaction Type', - deposit: 'Deposit', - rewardAccount: 'Reward Account' - }, - memory: 'Memory', - step: 'Step', - anchor: { - hash: 'Anchor Hash', - url: 'Anchor URL' - }, - networkGroup: { - title: 'Network Group', - maxBBSize: 'Max BB Size', - maxTxSize: 'Max Tx Size', - maxBHSize: 'Max BH Size', - maxValSize: 'Max Val Size', - maxTxExUnits: 'Max TX Ex Units', - maxBlockExUnits: 'Max BLK Ex Units', - maxCollateralInputs: 'Max Coll Inputs', - tooltip: { - maxBBSize: 'Max block body size', - maxTxSize: 'Max transaction size', - maxBHSize: 'Max block header size', - maxValSize: 'Max size of a serialized asset value', - maxTxExUnits: 'Max script execution units in a single transaction', - maxBlockExUnits: 'Max script execution units in a single block', - maxCollateralInputs: 'Max number of collateral inputs' - } - }, - economicGroup: { - title: 'Economic Group', - minFeeA: 'Min Fee A', - minFeeB: 'Min Fee B', - keyDeposit: 'Key Deposit', - poolDeposit: 'Pool Deposit', - rho: 'Rho', - tau: 'Tau', - minPoolCost: 'Min Pool Cost', - coinsPerUTxOByte: 'Coins/UTxO Byte', - prices: 'Price', - tooltip: { - minFeeA: 'Min fee coefficient', - minFeeB: 'Min fee constant', - keyDeposit: 'Delegation key Lovelace deposit', - poolDeposit: 'Pool registration Lovelace deposit', - rho: 'Monetary expansion', - tau: 'Treasury expansion', - minPoolCost: 'Min fixed rewards cut for pools', - coinsPerUTxOByte: 'Min Lovelace deposit per byte of serialized UTxO', - prices: 'Prices of Plutus execution units' - } - }, - technicalGroup: { - title: 'Technical Group', - a0: 'A0', - eMax: 'EMax', - nOpt: 'NOpt', - costModels: 'Cost Models', - collateralPercentage: 'Coll Percentage', - tooltip: { - a0: 'Pool pledge influence', - eMax: 'Pool retirement maximum epoch', - nOpt: 'Desired number of pools', - costModels: 'Plutus execution cost models', - collateralPercentage: 'Proportion of collateral needed for scripts' - } - }, - governanceGroup: { - title: 'Governance Group', - govActionLifetime: 'Gov Act Lifetime', - govActionDeposit: 'Gov Act Deposit', - drepDeposit: 'DRep Deposit', - drepActivity: 'DRep Activity', - ccMinSize: 'CC Min Size', - ccMaxTermLength: 'CC Max Term Length', - dRepVotingThresholds: { - title: 'Governance voting thresholds', - motionNoConfidence: 'Motion No Conf', - committeeNormal: 'Comm Normal', - committeeNoConfidence: 'Comm No Conf', - updateConstitution: 'Update Const', - hardForkInitiation: 'Hard Fork Init', - ppNetworkGroup: 'PP Network Grp', - ppEconomicGroup: 'PP Economic Grp', - ppTechnicalGroup: 'PP Technical Grp', - ppGovernanceGroup: 'PP Governance Grp', - treasuryWithdrawal: 'Treasury Withdraw' - }, - tooltip: { - govActionLifetime: 'governance action maximum lifetime in epochs', - govActionDeposit: 'governance action deposit', - drepDeposit: 'DRep deposit amount', - drepActivity: 'DRep activity period in epochs', - ccMinSize: 'Min constitutional committee size', - ccMaxTermLength: 'Max term length (in epochs) for the constitutional committee members', - dRepVotingThresholds: { - title: 'DRep voting thresholds', - motionNoConfidence: '1. Motion of no-confidence', - committeeNormal: '2a. New committee/threshold (normal state)', - committeeNoConfidence: '2b. New committee/threshold (state of no-confidence)', - updateConstitution: '3. Update to the Constitution or proposal policy', - hardForkInitiation: '4. Hard-fork initiation', - ppNetworkGroup: '5a. Protocol parameter changes, network group', - ppEconomicGroup: '5b. Protocol parameter changes, economic group', - ppTechnicalGroup: '5c. Protocol parameter changes, technical group', - ppGovernanceGroup: '5d. Protocol parameter changes, governance group', - treasuryWithdrawal: '6. Treasury withdrawal' - } - } - } } }; @@ -234,10 +114,3 @@ export const Overview: Story = { ...data } }; - -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeAction.tsx b/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeAction.tsx index 13ae37171..bbd924dcb 100644 --- a/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeAction.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeAction.tsx @@ -1,91 +1,269 @@ import React from 'react'; -import { Box, Grid, Flex, Divider, Metadata, MetadataLink, Cell } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../../DappInfo'; -import { ErrorPane } from '@lace/common'; -import { TransactionDetails } from '../components/TransactionDetails'; +import { Box, Grid, Divider, Metadata, MetadataLink, Cell } from '@lace/ui'; +import { ProposalProcedureTransactionDetails } from '../components/ProposalProcedureTransactionDetails'; import * as Types from './ParameterChangeActionTypes'; import { EconomicGroup } from './EconomicGroup'; import { NetworkGroup } from './NetworkGroup'; import { TechnicalGroup } from './TechnicalGroup'; import { GovernanceGroup } from './GovernanceGroup'; import { Card } from '../components/Card'; +import { useTranslation } from 'react-i18next'; interface ParameterChangeActionProps { - dappInfo: Omit; - errorMessage?: string; data: Types.Data; - translations: Types.Translations; } export const ParameterChangeAction = ({ - dappInfo, - errorMessage, - data: { txDetails, protocolParamUpdate, anchor }, - translations + data: { txDetails, protocolParamUpdate, anchor } }: ParameterChangeActionProps): JSX.Element => { + const { t } = useTranslation(); const { economicGroup, governanceGroup, networkGroup, technicalGroup, maxTxExUnits, maxBlockExUnits } = protocolParamUpdate; + // TODO: consider encapsulating it inside the component itself, check if all the translations have the fallback to the parent int provider (LW-9920) + + const translations: Types.Translations = { + txDetails: { + title: t('core.ProposalProcedure.txDetails.title'), + txType: t('core.ProposalProcedure.txDetails.txType'), + deposit: t('core.ProposalProcedure.txDetails.deposit'), + rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') + }, + anchor: { + url: t('core.ProposalProcedure.procedure.anchor.url'), + hash: t('core.ProposalProcedure.procedure.anchor.hash') + }, + memory: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.memory'), + step: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.step'), + networkGroup: { + title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.title'), + maxBBSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBBSize'), + maxTxSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxTxSize'), + maxBHSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBHSize'), + maxValSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxValSize'), + maxTxExUnits: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxTxExUnits'), + maxBlockExUnits: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxBlockExUnits'), + maxCollateralInputs: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.maxCollateralInputs' + ), + tooltip: { + maxBBSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBBSize'), + maxTxSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxTxSize'), + maxBHSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBHSize'), + maxValSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxValSize'), + maxTxExUnits: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxTxExUnits' + ), + maxBlockExUnits: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxBlockExUnits' + ), + maxCollateralInputs: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.networkGroup.tooltip.maxCollateralInputs' + ) + } + }, + economicGroup: { + title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.title'), + minFeeA: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minFeeA'), + minFeeB: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minFeeB'), + keyDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.keyDeposit'), + poolDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.poolDeposit'), + rho: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.rho'), + tau: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tau'), + minPoolCost: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.minPoolCost'), + coinsPerUTxOByte: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.coinsPerUTxOByte'), + prices: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.prices'), + tooltip: { + minFeeA: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minFeeA'), + minFeeB: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minFeeB'), + keyDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.keyDeposit'), + poolDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.poolDeposit'), + rho: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.rho'), + tau: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.tau'), + minPoolCost: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.minPoolCost'), + coinsPerUTxOByte: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.coinsPerUTxOByte' + ), + prices: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.economicGroup.tooltip.prices') + } + }, + technicalGroup: { + title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.title'), + a0: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.a0'), + eMax: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.eMax'), + nOpt: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.nOpt'), + costModels: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.costModels'), + collateralPercentage: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.collateralPercentage' + ), + tooltip: { + a0: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.a0'), + eMax: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.eMax'), + nOpt: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.nOpt'), + costModels: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.costModels'), + collateralPercentage: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.technicalGroup.tooltip.collateralPercentage' + ) + } + }, + governanceGroup: { + title: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.title'), + govActionLifetime: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.govActionLifetime' + ), + govActionDeposit: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.govActionDeposit' + ), + drepDeposit: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.drepDeposit'), + drepActivity: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.drepActivity'), + ccMinSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.ccMinSize'), + ccMaxTermLength: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.ccMaxTermLength'), + dRepVotingThresholds: { + title: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.title' + ), + motionNoConfidence: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.motionNoConfidence' + ), + committeeNormal: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.committeeNormal' + ), + committeeNoConfidence: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.committeeNoConfidence' + ), + updateConstitution: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.updateConstitution' + ), + hardForkInitiation: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.hardForkInitiation' + ), + ppNetworkGroup: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppNetworkGroup' + ), + ppEconomicGroup: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppEconomicGroup' + ), + ppTechnicalGroup: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppTechnicalGroup' + ), + ppGovernanceGroup: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.ppGovernanceGroup' + ), + treasuryWithdrawal: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.dRepVotingThresholds.treasuryWithdrawal' + ) + }, + tooltip: { + govActionLifetime: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.govActionLifetime' + ), + govActionDeposit: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.govActionDeposit' + ), + drepDeposit: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.drepDeposit' + ), + drepActivity: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.drepActivity' + ), + ccMinSize: t('core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.ccMinSize'), + ccMaxTermLength: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.ccMaxTermLength' + ), + dRepVotingThresholds: { + title: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.title' + ), + motionNoConfidence: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.motionNoConfidence' + ), + committeeNormal: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.committeeNormal' + ), + committeeNoConfidence: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.committeeNoConfidence' + ), + updateConstitution: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.updateConstitution' + ), + hardForkInitiation: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.hardForkInitiation' + ), + ppNetworkGroup: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppNetworkGroup' + ), + ppEconomicGroup: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppEconomicGroup' + ), + ppTechnicalGroup: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppTechnicalGroup' + ), + ppGovernanceGroup: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.ppGovernanceGroup' + ), + treasuryWithdrawal: t( + 'core.ProposalProcedure.governanceAction.protocolParamUpdate.governanceGroup.tooltip.dRepVotingThresholds.treasuryWithdrawal' + ) + } + } + } + }; + return ( - - - - - {errorMessage && ( - - - - )} - - {/* tx details section */} - - <> - - - - - {anchor.txHashUrl ? ( - - ) : ( - - )} - - + + {/* tx details section */} + + <> - - - - - - + - - + {anchor.txHashUrl ? ( + + ) : ( + + )} - - - - - + + + + + + + + + + + + + + + + + ); }; diff --git a/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeActionTypes.ts b/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeActionTypes.ts index 90efec01d..38e0d6873 100644 --- a/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeActionTypes.ts +++ b/packages/core/src/ui/components/ProposalProcedures/ParameterChangeAction/ParameterChangeActionTypes.ts @@ -1,5 +1,5 @@ import * as ProcedureTypes from '../components/ProcedureTypes'; -import * as TxDetailsTypes from '../components/TransactionDetailsTypes'; +import * as TxDetailsTypes from '../components/ProposalProcedureTransactionDetailsTypes'; export interface Data { protocolParamUpdate: ProtocolParamUpdate; diff --git a/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsAction.stories.tsx b/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsAction.stories.tsx index 7aae0caa7..7424b0e5c 100644 --- a/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsAction.stories.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsAction.stories.tsx @@ -29,14 +29,8 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, data: { txDetails: { - txType: 'Treasury Withdrawals', deposit: '2000', rewardAccount: 'stake1u89sasnfyjtmgk8ydqfv3fdl52f36x3djedfnzfc9rkgzrcss5vgr' }, @@ -57,31 +51,6 @@ const data: ComponentProps = { index: '0', id: '26bfdcc75a7f4d0cd8c71f0189bc5ca5ad2f4a3db6240c82b5a0edac7f9203e0' } - }, - translations: { - txDetails: { - title: 'Transaction Details', - txType: 'Transaction Type', - deposit: 'Deposit', - rewardAccount: 'Reward Account' - }, - procedure: { - anchor: { - hash: 'Anchor Hash', - url: 'Anchor URL' - }, - title: 'Procedure' - }, - actionId: { - title: 'Action ID', - index: 'Index', - txId: 'TX ID' - }, - withdrawals: { - title: 'Withdrawal Details', - lovelace: 'Lovelace Withdrawn', - rewardAccount: 'Reward Account' - } } }; @@ -90,10 +59,3 @@ export const Overview: Story = { ...data } }; - -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsAction.tsx b/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsAction.tsx index 38a8d2196..b1e438403 100644 --- a/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsAction.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsAction.tsx @@ -1,71 +1,90 @@ -import React from 'react'; -import { Box, Grid, Flex, Divider, sx, Text, Metadata, Cell } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../../DappInfo'; -import { ErrorPane } from '@lace/common'; +import React, { useMemo } from 'react'; +import { Grid, Divider, sx, Text, Metadata, Cell } from '@lace/ui'; import * as Types from './TreasuryWithdrawalsActionTypes'; -import { TransactionDetails } from '../components/TransactionDetails'; +import { ProposalProcedureTransactionDetails } from '../components/ProposalProcedureTransactionDetails'; import { ActionId } from '../components/ActionId'; import { Procedure } from '../components/Procedure'; +import { useTranslation } from 'react-i18next'; interface TreasuryWithdrawalsActionProps { - dappInfo: Omit; - errorMessage?: string; data: Types.Data; - translations: Types.Translations; } export const TreasuryWithdrawalsAction = ({ - dappInfo, - errorMessage, - data: { txDetails, procedure, withdrawals, actionId }, - translations + data: { txDetails, procedure, withdrawals, actionId } }: TreasuryWithdrawalsActionProps): JSX.Element => { + const { t } = useTranslation(); + const textCss = sx({ color: '$text_primary' }); + const translations = useMemo( + () => ({ + txDetails: { + title: t('core.ProposalProcedure.txDetails.title'), + txType: t('core.ProposalProcedure.txDetails.txType'), + deposit: t('core.ProposalProcedure.txDetails.deposit'), + rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') + }, + procedure: { + title: t('core.ProposalProcedure.procedure.title'), + anchor: { + url: t('core.ProposalProcedure.procedure.anchor.url'), + hash: t('core.ProposalProcedure.procedure.anchor.hash') + } + }, + actionId: { + title: t('core.ProposalProcedure.governanceAction.actionId.title'), + index: t('core.ProposalProcedure.governanceAction.actionId.index'), + txId: t('core.ProposalProcedure.governanceAction.actionId.txId') + }, + withdrawals: { + title: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.title'), + rewardAccount: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.withdrawals.rewardAccount'), + lovelace: t('core.ProposalProcedure.governanceAction.treasuryWithdrawals.withdrawals.lovelace') + } + }), + [t] + ); + return ( - - - - - {errorMessage && ( - - - + + {/* tx details section */} + + + + + {/* procedure section */} + + + + {translations.withdrawals.title} + + + {withdrawals.map((withdrawal) => ( + + + + + + + + + ))} + {actionId && ( + <> + + + + + )} - - {/* tx details section */} - - - - - {/* procedure section */} - - - - {translations.withdrawals.title} - - - {withdrawals.map((withdrawal) => ( - - - - - - - - - ))} - {actionId && ( - <> - - - - - - )} - - + ); }; diff --git a/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsActionTypes.ts b/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsActionTypes.ts index 7de7a0fc0..cfc906569 100644 --- a/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsActionTypes.ts +++ b/packages/core/src/ui/components/ProposalProcedures/TreasuryWithdrawalsAction/TreasuryWithdrawalsActionTypes.ts @@ -1,6 +1,6 @@ import * as ProcedureTypes from '../components/ProcedureTypes'; import * as ActionIdTypes from '../components/ActionIdTypes'; -import * as TxDetailsTypes from '../components/TransactionDetailsTypes'; +import * as TxDetailsTypes from '../components/ProposalProcedureTransactionDetailsTypes'; export interface Data { actionId?: ActionIdTypes.Data; diff --git a/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionAction.stories.tsx b/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionAction.stories.tsx index cd807a979..3422b9ddf 100644 --- a/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionAction.stories.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionAction.stories.tsx @@ -29,14 +29,8 @@ export default meta; type Story = StoryObj; const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, data: { txDetails: { - txType: 'Hard Fork Initiation', deposit: '2000', rewardAccount: 'stake1u89sasnfyjtmgk8ydqfv3fdl52f36x3djedfnzfc9rkgzrcss5vgr' }, @@ -77,42 +71,6 @@ const data: ComponentProps = { denominator: '5', numerator: '1' } - }, - translations: { - txDetails: { - title: 'Transaction Details', - txType: 'Transaction Type', - deposit: 'Deposit', - rewardAccount: 'Reward Account' - }, - procedure: { - anchor: { - hash: 'Anchor Hash', - url: 'Anchor URL' - }, - title: 'Procedure' - }, - actionId: { - title: 'Action ID', - index: 'Index', - txId: 'TX ID' - }, - membersToBeAdded: { - title: 'Members To Be Added', - coldCredential: { - hash: 'Cold Credential Hash', - epoch: 'Epoch' - } - }, - membersToBeRemoved: { - title: 'Members To Be Removed', - hash: 'Hash' - }, - newQuorumThreshold: { - title: 'New Quorum Threshold', - denominator: 'Denominator', - numerator: 'Numerator' - } } }; @@ -121,10 +79,3 @@ export const Overview: Story = { ...data } }; - -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; diff --git a/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionAction.tsx b/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionAction.tsx index 97237316d..743c203ae 100644 --- a/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionAction.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionAction.tsx @@ -1,97 +1,118 @@ import React from 'react'; -import { Box, Grid, Flex, Divider, sx, Text, Metadata, Cell } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Grid, Divider, sx, Text, Metadata, Cell } from '@lace/ui'; import * as Types from './UpdateCommitteeActionTypes'; import { Procedure } from '../components/Procedure'; -import { TransactionDetails } from '../components/TransactionDetails'; +import { ProposalProcedureTransactionDetails } from '../components/ProposalProcedureTransactionDetails'; import { ActionId } from '../components/ActionId'; +import { useTranslation } from 'react-i18next'; interface UpdateCommitteeActionProps { - dappInfo: Omit; - errorMessage?: string; data: Types.Data; - translations: Types.Translations; } export const UpdateCommitteeAction = ({ - dappInfo, - errorMessage, - data: { procedure, txDetails, membersToBeAdded, membersToBeRemoved, actionId }, - translations + data: { procedure, txDetails, membersToBeAdded, membersToBeRemoved, actionId } }: UpdateCommitteeActionProps): JSX.Element => { + const { t } = useTranslation(); const textCss = sx({ color: '$text_primary' }); + const translations: Types.Translations = { + txDetails: { + title: t('core.ProposalProcedure.txDetails.title'), + txType: t('core.ProposalProcedure.txDetails.txType'), + deposit: t('core.ProposalProcedure.txDetails.deposit'), + rewardAccount: t('core.ProposalProcedure.txDetails.rewardAccount') + }, + procedure: { + title: t('core.ProposalProcedure.procedure.title'), + anchor: { + url: t('core.ProposalProcedure.procedure.anchor.url'), + hash: t('core.ProposalProcedure.procedure.anchor.hash') + } + }, + actionId: { + title: t('core.ProposalProcedure.governanceAction.actionId.title'), + index: t('core.ProposalProcedure.governanceAction.actionId.index'), + txId: t('core.ProposalProcedure.governanceAction.actionId.txId') + }, + membersToBeAdded: { + title: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.title'), + coldCredential: { + hash: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.coldCredential.hash'), + epoch: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeAdded.coldCredential.epoch') + } + }, + membersToBeRemoved: { + title: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeRemoved.title'), + hash: t('core.ProposalProcedure.governanceAction.updateCommitteeAction.membersToBeRemoved.hash') + } + }; + return ( - - - - - {errorMessage && ( - - - + + {/* tx details section */} + + + + + {/* procedure section */} + + + + + {membersToBeAdded.length > 0 && ( + <> + + + {translations.membersToBeAdded.title} + + + {membersToBeAdded.map(({ coldCredential, epoch }) => ( + + + + + + + + + ))} + + )} + {membersToBeRemoved.length > 0 && ( + <> + + + {translations.membersToBeRemoved.title} + + + {membersToBeRemoved.map(({ hash }) => ( + + + + + + + + + ))} + + )} + {actionId && ( + <> + + + + + )} - - {/* tx details section */} - - - - - {/* procedure section */} - - - - - {membersToBeAdded.length > 0 && ( - <> - - - {translations.membersToBeAdded.title} - - - {membersToBeAdded.map(({ coldCredential, epoch }) => ( - - - - - - - - - ))} - - )} - {membersToBeRemoved.length > 0 && ( - <> - - - {translations.membersToBeRemoved.title} - - - {membersToBeRemoved.map(({ hash }) => ( - - - - - - - - - ))} - - )} - {actionId && ( - <> - - - - - - )} - - + ); }; diff --git a/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionTypes.ts b/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionTypes.ts index ce8b90745..3484ff23f 100644 --- a/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionTypes.ts +++ b/packages/core/src/ui/components/ProposalProcedures/UpdateCommitteeAction/UpdateCommitteeActionTypes.ts @@ -1,6 +1,6 @@ import * as ProcedureTypes from '../components/ProcedureTypes'; import * as ActionIdTypes from '../components/ActionIdTypes'; -import * as TxDetailsTypes from '../components/TransactionDetailsTypes'; +import * as TxDetailsTypes from '../components/ProposalProcedureTransactionDetailsTypes'; interface MembersToBeAdded { coldCredential: { diff --git a/packages/core/src/ui/components/ProposalProcedures/components/TransactionDetails.tsx b/packages/core/src/ui/components/ProposalProcedures/components/ProposalProcedureTransactionDetails.tsx similarity index 51% rename from packages/core/src/ui/components/ProposalProcedures/components/TransactionDetails.tsx rename to packages/core/src/ui/components/ProposalProcedures/components/ProposalProcedureTransactionDetails.tsx index 8a21c6b00..465bc06a5 100644 --- a/packages/core/src/ui/components/ProposalProcedures/components/TransactionDetails.tsx +++ b/packages/core/src/ui/components/ProposalProcedures/components/ProposalProcedureTransactionDetails.tsx @@ -1,13 +1,20 @@ import React from 'react'; import { Metadata, Text, sx, Cell } from '@lace/ui'; -import * as Types from './TransactionDetailsTypes'; +import * as Types from './ProposalProcedureTransactionDetailsTypes'; interface Props { - data: Types.TxDetails; + txTitle: string; + deposit?: string; + rewardAccount?: string; translations: Types.Translations; } -export const TransactionDetails = ({ data, translations }: Props): JSX.Element => { +export const ProposalProcedureTransactionDetails = ({ + txTitle, + deposit, + rewardAccount, + translations +}: Props): JSX.Element => { const textCss = sx({ color: '$text_primary' }); @@ -20,16 +27,16 @@ export const TransactionDetails = ({ data, translations }: Props): JSX.Element = - + - {data.rewardAccount && ( + {rewardAccount && ( - + )} - {data.deposit && ( + {deposit && ( - + )} diff --git a/packages/core/src/ui/components/ProposalProcedures/components/TransactionDetailsTypes.ts b/packages/core/src/ui/components/ProposalProcedures/components/ProposalProcedureTransactionDetailsTypes.ts similarity index 91% rename from packages/core/src/ui/components/ProposalProcedures/components/TransactionDetailsTypes.ts rename to packages/core/src/ui/components/ProposalProcedures/components/ProposalProcedureTransactionDetailsTypes.ts index 744b83200..169db5a5c 100644 --- a/packages/core/src/ui/components/ProposalProcedures/components/TransactionDetailsTypes.ts +++ b/packages/core/src/ui/components/ProposalProcedures/components/ProposalProcedureTransactionDetailsTypes.ts @@ -1,5 +1,4 @@ export interface TxDetails { - txType: string; deposit?: string; rewardAccount?: string; } diff --git a/packages/core/src/ui/components/ResignCommitteeCertificate/ResignCommitteeCertificate.tsx b/packages/core/src/ui/components/ResignCommitteeCertificate/ResignCommitteeCertificate.tsx new file mode 100644 index 000000000..bbed8063b --- /dev/null +++ b/packages/core/src/ui/components/ResignCommitteeCertificate/ResignCommitteeCertificate.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { Cell, Grid, TransactionSummary } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; + +interface Translations { + labels: { + url: string; + hash: string; + coldCredential: string; + }; +} +interface Props { + metadata: { + coldCredential: string; + hash: string; + url: string; + }; +} + +export const ResignCommitteeCertificate = ({ metadata }: Props): JSX.Element => { + const { t } = useTranslation(); + + const translations: Translations = { + labels: { + coldCredential: t('core.activityDetails.certificateTitles.coldCredential'), + hash: t('core.DRepRegistration.hash'), + url: t('core.DRepRegistration.url') + } + }; + + return ( + + + + + + + + {metadata.url && ( + + + + )} + {metadata.hash && ( + + + + )} + + ); +}; diff --git a/packages/core/src/ui/components/ResignCommitteeCertificate/index.ts b/packages/core/src/ui/components/ResignCommitteeCertificate/index.ts new file mode 100644 index 000000000..d6e9d3dfd --- /dev/null +++ b/packages/core/src/ui/components/ResignCommitteeCertificate/index.ts @@ -0,0 +1 @@ +export { ResignCommitteeCertificate } from './ResignCommitteeCertificate'; diff --git a/packages/core/src/ui/components/VotingProcedures/VotingProcedures.stories.tsx b/packages/core/src/ui/components/VotingProcedures/VotingProcedures.stories.tsx index b44f16a91..0a0be2c8d 100644 --- a/packages/core/src/ui/components/VotingProcedures/VotingProcedures.stories.tsx +++ b/packages/core/src/ui/components/VotingProcedures/VotingProcedures.stories.tsx @@ -2,6 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { VotingProcedures } from './VotingProcedures'; import { ComponentProps } from 'react'; +import { Wallet } from '@lace/cardano'; const customViewports = { popup: { @@ -28,16 +29,15 @@ const meta: Meta = { export default meta; type Story = StoryObj; +const TX_HASH_URL = + 'https://cexplorer.io/address/addr1q9wlvfl74g9h8txw5v0lfew2gjsw9z56d5kj8mmv5d8tudcx9eh8zefr3cxuje02lu6tgy083xkl39rr5xkj483vvd6q8nlapq'; +const URL = 'https://shorturl.at/eK145'; + const data: ComponentProps = { - dappInfo: { - logo: 'https://cdn.mint.handle.me/favicon.png', - name: 'Mint', - url: 'https://preprod.mint.handle.me' - }, data: [ { voter: { - type: 'DRep', + type: Wallet.util.getVoterType(Wallet.Cardano.VoterType.dRepKeyHash), dRepId: 'drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp4' }, votes: [ @@ -45,35 +45,68 @@ const data: ComponentProps = { actionId: { index: 0, txHash: '26bfdcc75a7f4d0cd8c71f0189bc5ca5ad2f4a3db6240c82b5a0edac7f9203e0', - txHashUrl: - 'https://cexplorer.io/address/addr1q9wlvfl74g9h8txw5v0lfew2gjsw9z56d5kj8mmv5d8tudcx9eh8zefr3cxuje02lu6tgy083xkl39rr5xkj483vvd6q8nlapq' + txHashUrl: TX_HASH_URL }, votingProcedure: { anchor: { hash: '9067f223838d88b83f660c05eedf7f6f65c45de31e522c1bcb6a1eb287b17e89', - url: 'https://shorturl.at/eK145' + url: URL }, - vote: 'Yes' + vote: Wallet.util.getVote(Wallet.Cardano.Vote.yes) } } ] } - ], - translations: { - voterType: 'Voter Type', - procedureTitle: 'Procedure', - actionIdTitle: 'Action ID', - vote: 'Vote', - actionId: { - index: 'Index', - txHash: 'TX Hash' - }, - anchor: { - hash: 'Anchor Hash', - url: 'Anchor URL' + ] +}; + +const dataMultiple: ComponentProps = { + data: [ + { + voter: { + type: Wallet.util.getVoterType(Wallet.Cardano.VoterType.dRepKeyHash), + dRepId: 'drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp4' + }, + votes: [ + { + actionId: { + index: 0, + txHash: '26bfdcc75a7f4d0cd8c71f0189bc5ca5ad2f4a3db6240c82b5a0edac7f9203e0', + txHashUrl: TX_HASH_URL + }, + votingProcedure: { + anchor: { + hash: '9067f223838d88b83f660c05eedf7f6f65c45de31e522c1bcb6a1eb287b17e89', + url: URL + }, + vote: Wallet.util.getVote(Wallet.Cardano.Vote.yes) + } + } + ] }, - dRepId: 'DRep ID' - } + { + voter: { + type: Wallet.util.getVoterType(Wallet.Cardano.VoterType.dRepKeyHash), + dRepId: 'drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp4' + }, + votes: [ + { + actionId: { + index: 0, + txHash: '26bfdcc75a7f4d0cd8c71f0189bc5ca5ad2f4a3db6240c82b5a0edac7f9203e0', + txHashUrl: TX_HASH_URL + }, + votingProcedure: { + anchor: { + hash: '9067f223838d88b83f660c05eedf7f6f65c45de31e522c1bcb6a1eb287b17e89', + url: URL + }, + vote: Wallet.util.getVote(Wallet.Cardano.Vote.no) + } + } + ] + } + ] }; export const Overview: Story = { @@ -81,41 +114,9 @@ export const Overview: Story = { ...data } }; -export const WithError: Story = { - args: { - ...data, - errorMessage: 'Something went wrong' - } -}; export const MultipleVotes: Story = { args: { - ...data, - data: [ - ...data.data, - { - voter: { - type: 'DRep', - dRepId: 'drep1cs234l5mtapethapx8cq97nkpa27xf84phruh5f6jqxa78ymlp5' - }, - votes: [ - { - actionId: { - index: 0, - txHash: '26bfdcc75a7f4d0cd8c71f0189bc5ca5ad2f4a3db6240c82b5a0edac7f9203e0', - txHashUrl: - 'https://cexplorer.io/address/addr1q9wlvfl74g9h8txw5v0lfew2gjsw9z56d5kj8mmv5d8tudcx9eh8zefr3cxuje02lu6tgy083xkl39rr5xkj483vvd6q8nlapq' - }, - votingProcedure: { - anchor: { - hash: '9067f223838d88b83f660c05eedf7f6f65c45de31e522c1bcb6a1eb287b17e89', - url: 'https://shorturl.at/eK145' - }, - vote: 'Yes' - } - } - ] - } - ] + ...dataMultiple } }; diff --git a/packages/core/src/ui/components/VotingProcedures/VotingProcedures.tsx b/packages/core/src/ui/components/VotingProcedures/VotingProcedures.tsx index dc40824e7..615d9fa7f 100644 --- a/packages/core/src/ui/components/VotingProcedures/VotingProcedures.tsx +++ b/packages/core/src/ui/components/VotingProcedures/VotingProcedures.tsx @@ -1,11 +1,12 @@ import React, { Fragment } from 'react'; -import { Box, Cell, Grid, Flex, Metadata, MetadataLink, Text, Divider, sx } from '@lace/ui'; -import { DappInfo, DappInfoProps } from '../DappInfo'; -import { ErrorPane } from '@lace/common'; +import { Box, Cell, Grid, Metadata, MetadataLink, Text, Divider, sx } from '@lace/ui'; +import { useTranslation } from 'react-i18next'; +import { TranslationKey } from '@lace/translation'; +import { VoterTypeEnum, VotesEnum } from '@lace/cardano/dist/wallet/util'; type VotingProcedure = { voter: { - type: string; + type: VoterTypeEnum; dRepId?: string; }; votes: { @@ -15,7 +16,7 @@ type VotingProcedure = { txHashUrl?: string; // Dependent on having an explorer to link }; votingProcedure: { - vote: string; + vote: VotesEnum; anchor: { url: string; hash: string; @@ -25,43 +26,35 @@ type VotingProcedure = { }; interface Props { - dappInfo: Omit; - errorMessage?: string; data: VotingProcedure[]; - translations: { - actionIdTitle: string; - actionId: { - index: string; - txHash: string; - }; - anchor: { - url: string; - hash: string; - } | null; - dRepId: string; - procedureTitle: string; - vote: string; - voterType: string; - }; } const indexCounter = (text: string, idx: number, length: number): string => (length > 1 ? `${text} ${idx + 1}` : text); -export const VotingProcedures = ({ dappInfo, errorMessage, data, translations }: Props): JSX.Element => { +export const VotingProcedures = ({ data }: Props): JSX.Element => { + const { t } = useTranslation(); const textCss = sx({ color: '$text_primary' }); + const 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') + }; + return ( - - - - - {errorMessage && ( - - - - )} + <> {data.map(({ voter, votes }, idx) => ( 0 ? '$40' : '$0'}> @@ -71,7 +64,10 @@ export const VotingProcedures = ({ dappInfo, errorMessage, data, translations }: - + {voter.dRepId && ( @@ -89,7 +85,10 @@ export const VotingProcedures = ({ dappInfo, errorMessage, data, translations }: - + {votingProcedure.anchor && ( <> @@ -130,6 +129,6 @@ export const VotingProcedures = ({ dappInfo, errorMessage, data, translations }: ))} - + ); }; diff --git a/packages/core/src/ui/components/WalletSetup/WalletSetupConfirmationDialogProvider.tsx b/packages/core/src/ui/components/WalletSetup/WalletSetupConfirmationDialogProvider.tsx index 63336ef71..0ae4c6205 100644 --- a/packages/core/src/ui/components/WalletSetup/WalletSetupConfirmationDialogProvider.tsx +++ b/packages/core/src/ui/components/WalletSetup/WalletSetupConfirmationDialogProvider.tsx @@ -4,16 +4,16 @@ import { BehaviorSubject } from 'rxjs'; import { StartOverDialog } from '@ui/components/SharedWallet/StartOverDialog'; import { useTranslation } from 'react-i18next'; -interface Props { - children: React.ReactNode; -} - interface ContextType { isDialogOpen: boolean; shouldShowDialog$: BehaviorSubject; withConfirmationDialog: (confirmedCallback: () => void) => () => void; } +interface Props { + children: (value: ContextType) => React.ReactNode; +} + const WalletSetupConfirmationDialogContext = createContext(null); export const useWalletSetupConfirmationDialog = (): ContextType => { @@ -80,7 +80,7 @@ export const WalletSetupConfirmationDialogProvider = ({ children }: Props): Reac onOpenChanged: setIsDialogOpen }} /> - {children} + {children(value)} ); }; diff --git a/packages/core/src/ui/utils/governance-action-mocks.ts b/packages/core/src/ui/utils/governance-action-mocks.ts new file mode 100644 index 000000000..032cdd96f --- /dev/null +++ b/packages/core/src/ui/utils/governance-action-mocks.ts @@ -0,0 +1,221 @@ +/* eslint-disable new-cap */ +/* eslint-disable no-magic-numbers */ +import { Cardano } from '@cardano-sdk/core'; +import { Hash28ByteBase16, Hash32ByteBase16 } from '@cardano-sdk/crypto'; + +const DUMMY_DEPOSIT = '100000' as never as bigint; +const rewardAccount = Cardano.RewardAccount('stake_test1uqrw9tjymlm8wrwq7jk68n6v7fs9qz8z0tkdkve26dylmfc2ux2hj'); +const anchor = { + url: 'anchorUrl', + // eslint-disable-next-line new-cap + dataHash: Hash32ByteBase16(Buffer.from('anchorDataHashanchorDataHashanch').toString('hex')) +}; + +const hardForkInitiationAction = { + __typename: Cardano.GovernanceActionType.hard_fork_initiation_action +} as Cardano.HardForkInitiationAction; +const infoAction = { + __typename: Cardano.GovernanceActionType.info_action +} as Cardano.InfoAction; +const newConstitution = { + __typename: Cardano.GovernanceActionType.new_constitution +} as Cardano.NewConstitution; +const noConfidence = { + __typename: Cardano.GovernanceActionType.no_confidence +} as Cardano.NoConfidence; +const parameterChangeAction = { + __typename: Cardano.GovernanceActionType.parameter_change_action +} as Cardano.ParameterChangeAction; +const treasuryWithdrawalsAction = { + __typename: Cardano.GovernanceActionType.treasury_withdrawals_action +} as Cardano.TreasuryWithdrawalsAction; +const updateCommittee = { + __typename: Cardano.GovernanceActionType.update_committee +} as Cardano.UpdateCommittee; + +export const mockProposalProcedure: Record< + Cardano.GovernanceActionType, + { + governanceAction: Cardano.GovernanceAction; + deposit: Cardano.ProposalProcedure['deposit']; + rewardAccount: Cardano.ProposalProcedure['rewardAccount']; + anchor: Cardano.ProposalProcedure['anchor']; + } +> = { + [Cardano.GovernanceActionType.hard_fork_initiation_action]: { + deposit: DUMMY_DEPOSIT, + rewardAccount, + anchor, + governanceAction: { + ...hardForkInitiationAction, + protocolVersion: { + major: 5, + minor: 0 + } + } + }, + [Cardano.GovernanceActionType.info_action]: { + deposit: DUMMY_DEPOSIT, + rewardAccount, + anchor, + governanceAction: infoAction + }, + [Cardano.GovernanceActionType.new_constitution]: { + deposit: DUMMY_DEPOSIT, + rewardAccount, + anchor, + governanceAction: { + ...newConstitution, + constitution: { + anchor: { + dataHash: Hash32ByteBase16(Buffer.from('anchorDataHashanchorDataHashanch').toString('hex')), + url: 'https://www.someurl.io' + }, + scriptHash: Hash28ByteBase16(Buffer.from('1234567890123456789012345678').toString('hex')) + } + } + }, + [Cardano.GovernanceActionType.no_confidence]: { + deposit: DUMMY_DEPOSIT, + rewardAccount, + anchor, + governanceAction: noConfidence + }, + [Cardano.GovernanceActionType.parameter_change_action]: { + deposit: DUMMY_DEPOSIT, + rewardAccount, + anchor, + governanceAction: { + ...parameterChangeAction, + protocolParamUpdate: { + maxBlockBodySize: 1, + maxTxSize: 2, + maxBlockHeaderSize: 3, + maxValueSize: 4, + maxExecutionUnitsPerTransaction: { + memory: 5, + steps: 6 + }, + maxExecutionUnitsPerBlock: { + memory: 7, + steps: 8 + }, + maxCollateralInputs: 9, + stakeKeyDeposit: 10, + poolDeposit: 11, + minFeeCoefficient: 12, + minFeeConstant: 13, + treasuryExpansion: '14', + monetaryExpansion: '15', + minPoolCost: 16, + coinsPerUtxoByte: 17, + prices: { + memory: 18, + steps: 19 + }, + poolInfluence: '20', + poolRetirementEpochBound: 21, + desiredNumberOfPools: 22, + costModels: new Map([ + [0, [23, 24]], + [1, [25, 26]] + ]), + collateralPercentage: 27, + governanceActionDeposit: 28, + dRepDeposit: 29, + governanceActionValidityPeriod: Cardano.EpochNo(30), + dRepInactivityPeriod: Cardano.EpochNo(31), + minCommitteeSize: 32, + committeeTermLimit: 33, + dRepVotingThresholds: { + motionNoConfidence: { + numerator: 34, + denominator: 35 + }, + committeeNormal: { + numerator: 36, + denominator: 37 + }, + commiteeNoConfidence: { + numerator: 38, + denominator: 39 + }, + updateConstitution: { + numerator: 40, + denominator: 41 + }, + hardForkInitiation: { + numerator: 42, + denominator: 43 + }, + ppNetworkGroup: { + numerator: 44, + denominator: 45 + }, + ppEconomicGroup: { + numerator: 46, + denominator: 47 + }, + ppTechnicalGroup: { + numerator: 48, + denominator: 49 + }, + ppGovernanceGroup: { + numerator: 50, + denominator: 51 + }, + treasuryWithdrawal: { + numerator: 55, + denominator: 56 + } + } + } + } + }, + [Cardano.GovernanceActionType.treasury_withdrawals_action]: { + deposit: DUMMY_DEPOSIT, + rewardAccount, + anchor, + governanceAction: { + ...treasuryWithdrawalsAction, + withdrawals: new Set([ + { rewardAccount, coin: BigInt('10000000') }, + { rewardAccount, coin: BigInt('10000001') } + ]) + } + }, + [Cardano.GovernanceActionType.update_committee]: { + deposit: DUMMY_DEPOSIT, + rewardAccount, + anchor, + governanceAction: { + ...updateCommittee, + membersToBeAdded: new Set([ + { + coldCredential: { + type: 0, + hash: Hash28ByteBase16(Buffer.from('updateCommitteecoldCredenti1').toString('hex')) + }, + epoch: Cardano.EpochNo(1) + }, + { + coldCredential: { + type: 1, + hash: Hash28ByteBase16(Buffer.from('updateCommitteecoldCredenti2').toString('hex')) + }, + epoch: Cardano.EpochNo(2) + } + ]), + membersToBeRemoved: new Set([ + { + type: 0, + hash: Hash28ByteBase16(Buffer.from('updateCommitteecoldCredenti2').toString('hex')) + }, + { + type: 1, + hash: Hash28ByteBase16(Buffer.from('updateCommitteecoldCredenti3').toString('hex')) + } + ]) + } + } +}; diff --git a/packages/core/src/ui/utils/governance-action.ts b/packages/core/src/ui/utils/governance-action.ts new file mode 100644 index 000000000..aa36d5bc8 --- /dev/null +++ b/packages/core/src/ui/utils/governance-action.ts @@ -0,0 +1,377 @@ +import { Cardano } from '@cardano-sdk/core'; +import { Wallet } from '@lace/cardano'; +import { formatPercentages } from '@lace/common'; +import { + HardForkInitiationAction, + InfoAction, + NewConstitutionAction, + NoConfidenceAction, + ParameterChangeAction, + TreasuryWithdrawalsAction, + UpdateCommitteeAction +} from '../components/ProposalProcedures'; + +export const getParameterChangeActionViewData = ({ + governanceAction, + deposit, + rewardAccount, + anchor, + cardanoCoin, + explorerBaseUrl +}: { + governanceAction: Cardano.ParameterChangeAction; + deposit: Cardano.ProposalProcedure['deposit']; + rewardAccount: Cardano.ProposalProcedure['rewardAccount']; + anchor: Cardano.ProposalProcedure['anchor']; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; +}): Parameters[0]['data'] => { + const { + protocolParamUpdate: { + maxBlockBodySize, + maxTxSize, + maxBlockHeaderSize, + maxValueSize, + maxExecutionUnitsPerTransaction, + maxExecutionUnitsPerBlock, + maxCollateralInputs, + stakeKeyDeposit, + poolDeposit, + minFeeCoefficient, + minFeeConstant, + treasuryExpansion, + monetaryExpansion, + minPoolCost, + coinsPerUtxoByte, + prices, + poolInfluence, + poolRetirementEpochBound, + desiredNumberOfPools, + costModels, + collateralPercentage, + governanceActionDeposit, + dRepDeposit, + governanceActionValidityPeriod, + dRepInactivityPeriod, + minCommitteeSize, + committeeTermLimit, + dRepVotingThresholds: { + motionNoConfidence, + committeeNormal, + commiteeNoConfidence, + updateConstitution, + hardForkInitiation, + ppNetworkGroup, + ppEconomicGroup, + ppTechnicalGroup, + ppGovernanceGroup, + treasuryWithdrawal + } + } + } = governanceAction; + + return { + txDetails: { + deposit: Wallet.util.getFormattedAmount({ + amount: deposit.toString(), + cardanoCoin + }), + rewardAccount + }, + anchor: { + url: anchor.url, + hash: anchor.dataHash, + txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` + }, + protocolParamUpdate: { + maxTxExUnits: { + memory: maxExecutionUnitsPerTransaction.memory.toString(), + step: maxExecutionUnitsPerTransaction.steps.toString() + }, + maxBlockExUnits: { + memory: maxExecutionUnitsPerBlock.memory.toString(), + step: maxExecutionUnitsPerBlock.steps.toString() + }, + networkGroup: { + maxBBSize: maxBlockBodySize.toString(), + maxTxSize: maxTxSize.toString(), + maxBHSize: maxBlockHeaderSize.toString(), + maxValSize: maxValueSize.toString(), + maxCollateralInputs: maxCollateralInputs.toString() + }, + economicGroup: { + minFeeA: minFeeCoefficient.toString(), + minFeeB: minFeeConstant.toString(), + keyDeposit: stakeKeyDeposit.toString(), + poolDeposit: poolDeposit.toString(), + rho: monetaryExpansion, + tau: treasuryExpansion, + minPoolCost: minPoolCost.toString(), + coinsPerUTxOByte: coinsPerUtxoByte.toString(), + price: { + memory: prices.memory.toString(), + step: prices.steps.toString() + } + }, + technicalGroup: { + a0: poolInfluence, + eMax: poolRetirementEpochBound.toString(), + nOpt: desiredNumberOfPools.toString(), + costModels: { + PlutusV1: Object.entries(costModels.get(Cardano.PlutusLanguageVersion.V1)).reduce( + (acc, cur) => ({ ...acc, [cur[0]]: cur[1] }), + {} + ), + PlutusV2: Object.entries(costModels.get(Cardano.PlutusLanguageVersion.V2)).reduce( + (acc, cur) => ({ ...acc, [cur[0]]: cur[1] }), + {} + ) + }, + collateralPercentage: collateralPercentage.toString() + }, + governanceGroup: { + govActionLifetime: governanceActionValidityPeriod.toString(), + govActionDeposit: governanceActionDeposit.toString(), + drepDeposit: dRepDeposit.toString(), + drepActivity: dRepInactivityPeriod.toString(), + ccMinSize: minCommitteeSize.toString(), + ccMaxTermLength: committeeTermLimit.toString(), + dRepVotingThresholds: { + motionNoConfidence: formatPercentages(motionNoConfidence.numerator / motionNoConfidence.denominator), + committeeNormal: formatPercentages(committeeNormal.numerator / committeeNormal.denominator), + committeeNoConfidence: formatPercentages(commiteeNoConfidence.numerator / commiteeNoConfidence.denominator), + updateToConstitution: formatPercentages(updateConstitution.numerator / updateConstitution.denominator), + hardForkInitiation: formatPercentages(hardForkInitiation.numerator / hardForkInitiation.denominator), + ppNetworkGroup: formatPercentages(ppNetworkGroup.numerator / ppNetworkGroup.denominator), + ppEconomicGroup: formatPercentages(ppEconomicGroup.numerator / ppEconomicGroup.denominator), + ppTechnicalGroup: formatPercentages(ppTechnicalGroup.numerator / ppTechnicalGroup.denominator), + ppGovGroup: formatPercentages(ppGovernanceGroup.numerator / ppGovernanceGroup.denominator), + treasuryWithdrawal: formatPercentages(treasuryWithdrawal.numerator / treasuryWithdrawal.denominator) + } + } + } + }; +}; + +export const getHardForkInitiationActionViewData = ({ + governanceAction, + deposit, + rewardAccount, + anchor, + cardanoCoin, + explorerBaseUrl +}: { + governanceAction: Cardano.HardForkInitiationAction; + deposit: Cardano.ProposalProcedure['deposit']; + rewardAccount: Cardano.ProposalProcedure['rewardAccount']; + anchor: Cardano.ProposalProcedure['anchor']; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; +}): Parameters[0]['data'] => ({ + txDetails: { + deposit: Wallet.util.getFormattedAmount({ + amount: deposit.toString(), + cardanoCoin + }), + rewardAccount + }, + procedure: { + anchor: { + url: anchor.url, + hash: anchor.dataHash, + txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` + } + }, + protocolVersion: { + major: governanceAction.protocolVersion.major.toString(), + minor: governanceAction.protocolVersion.minor.toString() + }, + ...(governanceAction.governanceActionId && { + actionId: { + index: governanceAction.governanceActionId.actionIndex.toString(), + id: governanceAction.governanceActionId.id || '' + } + }) +}); + +export const getInfoActionViewData = ({ + anchor, + explorerBaseUrl +}: { + anchor: Cardano.ProposalProcedure['anchor']; + explorerBaseUrl: string; +}): Parameters[0]['data'] => ({ + txDetails: {}, + procedure: { + anchor: { + url: anchor.url, + hash: anchor.dataHash, + txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` + } + } +}); + +export const getNewConstitutionActionViewData = ({ + governanceAction, + deposit, + rewardAccount, + anchor, + cardanoCoin, + explorerBaseUrl +}: { + governanceAction: Cardano.NewConstitution; + deposit: Cardano.ProposalProcedure['deposit']; + rewardAccount: Cardano.ProposalProcedure['rewardAccount']; + anchor: Cardano.ProposalProcedure['anchor']; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; +}): Parameters[0]['data'] => ({ + txDetails: { + deposit: Wallet.util.getFormattedAmount({ + amount: deposit.toString(), + cardanoCoin + }), + rewardAccount + }, + procedure: { + anchor: { + url: anchor.url, + hash: anchor.dataHash, + txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` + } + }, + ...(governanceAction.governanceActionId && { + actionId: { + index: governanceAction.governanceActionId.actionIndex.toString(), + id: governanceAction.governanceActionId.id || '' + } + }), + constitution: { + anchor: { + dataHash: governanceAction.constitution.anchor.dataHash.toString(), + url: governanceAction.constitution.anchor.url.toString() + }, + ...(governanceAction.constitution.scriptHash && { scriptHash: governanceAction.constitution.scriptHash.toString() }) + } +}); + +export const getNoConfidenceActionViewData = ({ + governanceAction, + deposit, + rewardAccount, + anchor, + cardanoCoin, + explorerBaseUrl +}: { + governanceAction: Cardano.NoConfidence; + deposit: Cardano.ProposalProcedure['deposit']; + rewardAccount: Cardano.ProposalProcedure['rewardAccount']; + anchor: Cardano.ProposalProcedure['anchor']; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; +}): Parameters[0]['data'] => ({ + txDetails: { + deposit: Wallet.util.getFormattedAmount({ + amount: deposit.toString(), + cardanoCoin + }), + rewardAccount + }, + procedure: { + anchor: { + url: anchor.url, + hash: anchor.dataHash, + txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` + } + }, + ...(governanceAction.governanceActionId && { + actionId: { + index: governanceAction.governanceActionId.actionIndex.toString(), + id: governanceAction.governanceActionId.id || '' + } + }) +}); + +export const getTreasuryWithdrawalsActionViewData = ({ + governanceAction, + deposit, + anchor, + rewardAccount, + cardanoCoin, + explorerBaseUrl +}: { + governanceAction: Cardano.TreasuryWithdrawalsAction; + deposit: Cardano.ProposalProcedure['deposit']; + rewardAccount: Cardano.ProposalProcedure['rewardAccount']; + anchor: Cardano.ProposalProcedure['anchor']; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; +}): Parameters[0]['data'] => ({ + txDetails: { + deposit: Wallet.util.getFormattedAmount({ + amount: deposit.toString(), + cardanoCoin + }), + rewardAccount + }, + procedure: { + anchor: { + url: anchor.url, + hash: anchor.dataHash, + txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` + } + }, + withdrawals: [...governanceAction.withdrawals].map((withdrawal) => ({ + rewardAccount: withdrawal.rewardAccount.toString(), + lovelace: Wallet.util.getFormattedAmount({ + amount: withdrawal.coin.toString(), + cardanoCoin + }) + })) +}); + +export const getUpdateCommitteeActionViewData = ({ + anchor, + cardanoCoin, + deposit, + explorerBaseUrl, + governanceAction, + rewardAccount +}: { + governanceAction: Cardano.UpdateCommittee; + deposit: Cardano.ProposalProcedure['deposit']; + rewardAccount: Cardano.ProposalProcedure['rewardAccount']; + anchor: Cardano.ProposalProcedure['anchor']; + cardanoCoin: Wallet.CoinId; + explorerBaseUrl: string; +}): Parameters[0]['data'] => ({ + txDetails: { + deposit: Wallet.util.getFormattedAmount({ + amount: deposit.toString(), + cardanoCoin + }), + rewardAccount + }, + procedure: { + anchor: { + url: anchor.url, + hash: anchor.dataHash, + txHashUrl: `${explorerBaseUrl}/${anchor.dataHash}` + } + }, + ...(governanceAction.governanceActionId && { + actionId: { + index: governanceAction.governanceActionId.actionIndex.toString(), + id: governanceAction.governanceActionId.id || '' + } + }), + membersToBeAdded: [...governanceAction.membersToBeAdded].map(({ coldCredential: { hash }, epoch }) => ({ + coldCredential: { + hash: hash.toString() + }, + epoch: epoch.toString() + })), + membersToBeRemoved: [...governanceAction.membersToBeRemoved].map(({ hash }) => ({ + hash: hash.toString() + })) +}); diff --git a/packages/core/src/ui/utils/index.ts b/packages/core/src/ui/utils/index.ts index 1892c7749..bc298cbc5 100644 --- a/packages/core/src/ui/utils/index.ts +++ b/packages/core/src/ui/utils/index.ts @@ -2,3 +2,5 @@ export * from './sanitize-number'; export * from './handle'; export * from './address-form'; export * from './render-address-tag'; +export * from './governance-action'; +export * from './governance-action-mocks'; diff --git a/packages/core/src/ui/utils/voting-procedures-mock.ts b/packages/core/src/ui/utils/voting-procedures-mock.ts new file mode 100644 index 000000000..9b924d6c0 --- /dev/null +++ b/packages/core/src/ui/utils/voting-procedures-mock.ts @@ -0,0 +1,52 @@ +import { Wallet } from '@lace/cardano'; + +export const mockVotingProcedures = [ + { + voter: { + __typename: Wallet.Cardano.VoterType.dRepKeyHash, + credential: { + type: Wallet.Cardano.CredentialType.KeyHash, + hash: Wallet.Crypto.Hash28ByteBase16(Buffer.from('dRepCredentialHashdRepCrede1').toString('hex')) + } + }, + votes: [ + { + actionId: { + id: Wallet.Cardano.TransactionId('724a0a88b9470a714fc5bf84daf5851fa259a9b89e1a5453f6f5cd6595ad9820'), + actionIndex: 0 + }, + votingProcedure: { + vote: Wallet.Cardano.Vote.yes, + anchor: { + url: 'anchorUrl', + dataHash: Wallet.Crypto.Hash32ByteBase16(Buffer.from('anchorDataHashanchorDataHashanc1').toString('hex')) + } + } + } + ] + }, + { + voter: { + __typename: Wallet.Cardano.VoterType.ccHotKeyHash, + credential: { + type: Wallet.Cardano.CredentialType.KeyHash, + hash: Wallet.Crypto.Hash28ByteBase16(Buffer.from('dRepCredentialHashdRepCrede2').toString('hex')) + } + }, + votes: [ + { + actionId: { + id: Wallet.Cardano.TransactionId('55555a88b9470a714fc5bf84daf5851fa259a9b89e1a5453f6f5cd6595ad9820'), + actionIndex: 0 + }, + votingProcedure: { + vote: Wallet.Cardano.Vote.yes, + anchor: { + url: 'anchorUrl', + dataHash: Wallet.Crypto.Hash32ByteBase16(Buffer.from('anchorDataHashanchorDataHashanc2').toString('hex')) + } + } + } + ] + } +]; diff --git a/packages/e2e-tests/src/assert/topNavigationAssert.ts b/packages/e2e-tests/src/assert/topNavigationAssert.ts index c7abcf4c8..ade070f91 100644 --- a/packages/e2e-tests/src/assert/topNavigationAssert.ts +++ b/packages/e2e-tests/src/assert/topNavigationAssert.ts @@ -178,6 +178,11 @@ class TopNavigationAssert { expect(await MenuHeader.menuWalletName.getText()).to.equal(expectedWalletName); } + async assertSeeCustomAvatar(expectedImageSrc: string) { + await MenuHeader.avatarOnButton.waitForDisplayed(); + expect(await MenuHeader.avatarOnButton.getAttribute('src')).to.equal(expectedImageSrc); + } + async assertSeeRightSidePanelButton(shouldBeVisible: boolean) { await MenuHeader.rightSidePanelButton.waitForDisplayed({ reverse: !shouldBeVisible }); } diff --git a/packages/e2e-tests/src/assert/transactionsPageAssert.ts b/packages/e2e-tests/src/assert/transactionsPageAssert.ts index cdb1945fa..68270e5e6 100644 --- a/packages/e2e-tests/src/assert/transactionsPageAssert.ts +++ b/packages/e2e-tests/src/assert/transactionsPageAssert.ts @@ -5,6 +5,9 @@ import testContext from '../utils/testContext'; import { expect } from 'chai'; import { browser } from '@wdio/globals'; import { isPopupMode } from '../utils/pageUtils'; +import { ParsedCSSValue } from 'webdriverio'; +import { TransactionStyle } from '../types/transactionStyle'; +import { TransactionType } from '../types/transactionType'; export type ExpectedTransactionRowAssetDetails = { type: string; @@ -13,6 +16,8 @@ export type ExpectedTransactionRowAssetDetails = { }; class TransactionsPageAssert { + private readonly CSS_COLOR = 'color'; + assertSeeSkeleton = async (shouldBeVisible: boolean) => { await TransactionsPage.transactionsInfiniteScroll.waitForDisplayed({ reverse: !shouldBeVisible }); }; @@ -163,6 +168,24 @@ class TransactionsPageAssert { expect(tickerList.every((ticker) => ticker === expectedTicker)).to.be.true; } + + async assertSeeStylingForTxType(styling: TransactionStyle, txType: TransactionType) { + const index = await TransactionsPage.getIndexOfTxType(txType); + expect(await TransactionsPage.transactionsTableItemType(index).getText()).to.equal(txType); + + let expectedColors: string[]; + const amountElement = await TransactionsPage.transactionsTableItemTokensAmount(index); + if (styling === 'default - negative') { + expectedColors = ['#3d3b39', '#ffffff']; + expect((await amountElement.getText())[0]).to.equal('-'); + } else { + expectedColors = ['#2cb67d']; + expect((await amountElement.getText())[0]).to.not.equal('-'); + } + expect(((await amountElement.getCSSProperty(this.CSS_COLOR)) as ParsedCSSValue).parsed.hex).to.be.oneOf( + expectedColors + ); + } } export default new TransactionsPageAssert(); diff --git a/packages/e2e-tests/src/elements/NFTs/nftDetails.ts b/packages/e2e-tests/src/elements/NFTs/nftDetails.ts index 06d94297e..5bb9d3ea2 100644 --- a/packages/e2e-tests/src/elements/NFTs/nftDetails.ts +++ b/packages/e2e-tests/src/elements/NFTs/nftDetails.ts @@ -1,17 +1,19 @@ /* eslint-disable no-undef */ import { ChainablePromiseElement } from 'webdriverio'; import CommonDrawerElements from '../CommonDrawerElements'; +import testContext from '../../utils/testContext'; class NftDetails { private NFT_DETAILS_DRAWER = '[data-testid="nft-details-drawer"]'; private IMAGE = '[data-testid="nft-image"]'; + private SET_AS_AVATAR_BUTTON = '[data-testid="nft-set-as-avatar-button"]'; private TOKEN_INFO_SECTION = '[data-testid="nft-info"]'; private TOKEN_INFORMATION_LABEL = '[data-testid="nft-info-label"]'; private ATTRIBUTES_SECTION = '[data-testid="nft-attributes"]'; private ATTRIBUTES_LABEL = '[data-testid="nft-attributes-label"]'; private INFO_LIST_ITEM = '[data-testid="info-list-item"]'; private INFO_LIST_ITEM_KEY = '[data-testid="info-list-item-key"]'; - private INFO_LIST_ITEM_VALUE = '[data-testid="info-list-item-key"]'; + private INFO_LIST_ITEM_VALUE = '[data-testid="info-list-item-value"]'; private SEND_NFT_BUTTON = '#send-nft-btn'; private NFT_TITLE_ON_POPUP = '[data-testid="drawer-content"] h2'; @@ -43,6 +45,10 @@ class NftDetails { return this.drawerBody.$(this.IMAGE); } + get setAsAvatarButton() { + return this.drawerBody.$(this.SET_AS_AVATAR_BUTTON); + } + get tokenInfoSection() { return $(this.TOKEN_INFO_SECTION); } @@ -86,6 +92,17 @@ class NftDetails { get sendNFTButton() { return $(this.SEND_NFT_BUTTON); } + + async saveNFTDetails(): Promise { + const policyId = await this.policyIdValue.getText(); + const assetId = await this.assetIdValue.getText(); + const mediaUrl = await this.mediaUrlValue.getText(); + testContext.save('nftDetails', { policyId, assetId, mediaUrl }); + } + + async loadNFTDetails(): Promise { + return testContext.load('nftDetails'); + } } export default new NftDetails(); diff --git a/packages/e2e-tests/src/elements/transactionsPage.ts b/packages/e2e-tests/src/elements/transactionsPage.ts index 83eaecff3..ffe969998 100644 --- a/packages/e2e-tests/src/elements/transactionsPage.ts +++ b/packages/e2e-tests/src/elements/transactionsPage.ts @@ -108,6 +108,27 @@ class TransactionsPage { await browser.pause(1000); } } + async getIndexOfTxTypeWithoutScroll(txType: string): Promise { + const txTypes: string[] = []; + const tableItems = await $$(this.TRANSACTIONS_TABLE_ITEM_TYPE); + for (const tableItem of tableItems) { + txTypes.push(await tableItem.getText()); + } + return txTypes.indexOf(txType); + } + + async getIndexOfTxTypeWithScroll(txType: string): Promise { + await this.scrollToTheLastRow(); + return await this.getIndexOfTxTypeWithoutScroll(txType); + } + + async getIndexOfTxType(txType: string): Promise { + const index = await this.getIndexOfTxTypeWithoutScroll(txType); + if (index === -1) { + return await this.getIndexOfTxTypeWithScroll(txType); + } + return index; + } async saveNumberOfVisibleRows() { const numberOfRows = (await this.rows).length; diff --git a/packages/e2e-tests/src/features/NFTsExtended.feature b/packages/e2e-tests/src/features/NFTsExtended.feature index cac1dfa92..b33361943 100644 --- a/packages/e2e-tests/src/features/NFTsExtended.feature +++ b/packages/e2e-tests/src/features/NFTsExtended.feature @@ -57,7 +57,7 @@ Feature: LW-423: NFTs - Extended view Given I am on NFTs extended page When I click on a widget item with subtitle: "" Then I see a "" article with title "" - Examples: + Examples: | type | subtitle | | Glossary | What are collections? | | FAQ | How to buy an NFT? | @@ -89,3 +89,13 @@ Feature: LW-423: NFTs - Extended view And I enter a valid "shelley" address in the bundle 1 recipient's address When I press keyboard Escape button Then a popup asking if you're sure you'd like to close it is displayed + + @LW-10321 + Scenario: Extended-view - Setting up NFT as a wallet profile avatar + Given I am on NFTs extended page + And I left click on the NFT with name "LaceNFT" on NFTs page + And I am on a NFT details on the extended view for NFT with name: "LaceNFT" + And I save NFT details + And I click "Set as your wallet avatar" button on NFT details drawer + When I close the drawer by clicking close button + Then the NFT is set as a wallet profile avatar diff --git a/packages/e2e-tests/src/features/NFTsPopup.feature b/packages/e2e-tests/src/features/NFTsPopup.feature index a3a8562de..30e3b3b80 100644 --- a/packages/e2e-tests/src/features/NFTsPopup.feature +++ b/packages/e2e-tests/src/features/NFTsPopup.feature @@ -60,3 +60,14 @@ Feature: LW-411 Ext.PopUp - Collectibles/NFTs Scenario: Popup-view - NFT with image does not display fallback picture Given I am on NFTs popup page Then Verify that "Bison Coin" doesn't contain fallback image + + + @LW-10322 + Scenario: Popup-view - Setting up NFT as a wallet profile avatar + Given I am on NFTs popup page + And I left click on the NFT with name "LaceNFT" on NFTs page + And I am on a NFT details on the popup view for NFT with name: "LaceNFT" + And I save NFT details + And I click "Set as your wallet avatar" button on NFT details drawer + When I close the drawer by clicking back button + Then the NFT is set as a wallet profile avatar diff --git a/packages/e2e-tests/src/features/TransactionsExtended.feature b/packages/e2e-tests/src/features/TransactionsExtended.feature index 925c1a711..73f3d43cf 100644 --- a/packages/e2e-tests/src/features/TransactionsExtended.feature +++ b/packages/e2e-tests/src/features/TransactionsExtended.feature @@ -124,3 +124,18 @@ Feature: Transactions - Extended view When the Sent transaction is displayed with value: "24.79 tADA" and tokens count 1 When I click on a transaction: 1 Then The Tx details are displayed as "core.activityDetails.sent" for ADA with value: 24.79 and wallet: "WalletReceiveSimpleTransactionE2E" address + + @LW-9914 @Testnet + Scenario Outline: Extended View - transaction list - styling: applied to tx type: + Given I am on Transactions extended page + When I scroll to the row with transaction type: + Then I see styling for transaction type: + Examples: + | tx_type | styling | + | Sent | default - negative | + | Received | green - positive | + | Self Transaction | default - negative | + | Rewards | green - positive | + | Delegation | default - negative | + | Stake Key De-Registration | green - positive | + | Stake Key Registration | default - negative | diff --git a/packages/e2e-tests/src/features/TransactionsPopup.feature b/packages/e2e-tests/src/features/TransactionsPopup.feature index e90dd5c6f..e1700783b 100644 --- a/packages/e2e-tests/src/features/TransactionsPopup.feature +++ b/packages/e2e-tests/src/features/TransactionsPopup.feature @@ -91,3 +91,18 @@ Feature: Transactions - Popup view Then I see 2 opened tab(s) When I switch to last window Then I see cexplorer url with correct transaction hash + + @LW-10596 @Testnet + Scenario Outline: Popup View - transaction list - styling: applied to tx type: + Given I am on Transactions popup page + When I scroll to the row with transaction type: + Then I see styling for transaction type: + Examples: + | tx_type | styling | + | Sent | default - negative | + | Received | green - positive | + | Self Transaction | default - negative | + | Rewards | green - positive | + | Delegation | default - negative | + | Stake Key De-Registration | green - positive | + | Stake Key Registration | default - negative | diff --git a/packages/e2e-tests/src/steps/navigationTopSteps.ts b/packages/e2e-tests/src/steps/navigationTopSteps.ts index 52d12fce3..30c1c6e0f 100644 --- a/packages/e2e-tests/src/steps/navigationTopSteps.ts +++ b/packages/e2e-tests/src/steps/navigationTopSteps.ts @@ -4,6 +4,7 @@ import menuHeaderPageObject from '../pageobject/menuHeaderPageObject'; import menuHeaderNetwork from '../elements/menuHeaderNetwork'; import MenuHeader from '../elements/menuHeader'; import { browser } from '@wdio/globals'; +import nftDetails from '../elements/NFTs/nftDetails'; When(/I click the menu button/, async () => { await menuHeaderPageObject.clickMenuButton(); @@ -107,6 +108,11 @@ Then(/^header menu displays "([^"]*)" as a wallet name$/, async (walletName) => await topNavigationAssert.assertSeeWalletName(walletName); }); +Then(/^the NFT is set as a wallet profile avatar$/, async () => { + const savedNftDetails = await nftDetails.loadNFTDetails(); + await topNavigationAssert.assertSeeCustomAvatar(savedNftDetails.mediaUrl); +}); + When(/^I close header menu$/, async () => { await menuHeaderPageObject.closeMenu(); }); diff --git a/packages/e2e-tests/src/steps/nftsCommonSteps.ts b/packages/e2e-tests/src/steps/nftsCommonSteps.ts index c42f1f31b..01bc979f9 100644 --- a/packages/e2e-tests/src/steps/nftsCommonSteps.ts +++ b/packages/e2e-tests/src/steps/nftsCommonSteps.ts @@ -15,6 +15,7 @@ import NftsPage from '../elements/NFTs/nftsPage'; import { browser } from '@wdio/globals'; import { expect } from 'chai'; import TokenSelectionPage from '../elements/newTransaction/tokenSelectionPage'; +import nftDetails from '../elements/NFTs/nftDetails'; When( /^I (left|right) click on the NFT with name "([^"]*)" on NFTs page$/, @@ -149,3 +150,7 @@ When(/^I open NFT receiving HD wallet$/, async () => { When(/^I save all NFTs that I have$/, async () => { await nftsPageObject.saveNfts(); }); + +When(/^I save NFT details$/, async () => { + await nftDetails.saveNFTDetails(); +}); diff --git a/packages/e2e-tests/src/steps/nftsExtendedSteps.ts b/packages/e2e-tests/src/steps/nftsExtendedSteps.ts index 13ae62185..6d4c3bcc4 100644 --- a/packages/e2e-tests/src/steps/nftsExtendedSteps.ts +++ b/packages/e2e-tests/src/steps/nftsExtendedSteps.ts @@ -20,10 +20,18 @@ Given( } ); -When(/^I click "Send NFT" button on NFT details drawer$/, async () => { - await NftDetails.sendNFTButton.waitForStable(); - await NftDetails.sendNFTButton.click(); -}); +When( + /^I click "(Send NFT|Set as your wallet avatar)" button on NFT details drawer$/, + async (button: 'Send NFT' | 'Set as your wallet avatar') => { + if (button === 'Send NFT') { + await NftDetails.sendNFTButton.waitForStable(); + await NftDetails.sendNFTButton.click(); + } else if (button === 'Set as your wallet avatar') { + await NftDetails.setAsAvatarButton.waitForStable(); + await NftDetails.setAsAvatarButton.click(); + } + } +); Then(/^"Send NFT" button (is|is not) displayed on NFT details drawer$/, async (shouldBeDisplayed: 'is' | 'is not') => { await nftAssert.assertSeeSendNFTButton(shouldBeDisplayed === 'is'); diff --git a/packages/e2e-tests/src/steps/transactionsSteps.ts b/packages/e2e-tests/src/steps/transactionsSteps.ts index 71332fc6d..4b48aa23c 100644 --- a/packages/e2e-tests/src/steps/transactionsSteps.ts +++ b/packages/e2e-tests/src/steps/transactionsSteps.ts @@ -9,6 +9,8 @@ import TransactionDetailsPage from '../elements/transactionDetails'; import TransactionsPage from '../elements/transactionsPage'; import { Logger } from '../support/logger'; import { browser } from '@wdio/globals'; +import { TransactionType } from '../types/transactionType'; +import { TransactionStyle } from '../types/transactionStyle'; Given(/^I am on the Transactions section - Extended view$/, async () => { await mainMenuPageObject.navigateToSection('Transactions', 'extended'); @@ -163,6 +165,23 @@ When(/^I scroll to the last row$/, async () => { await TransactionsPage.scrollToTheLastRow(); }); +When( + /^I scroll to the row with transaction type: (Sent|Received|Self Transaction|Rewards|Delegation|Stake Key Registration|Stake Key De-Registration)$/, + async (txType: TransactionType) => { + const index = await TransactionsPage.getIndexOfTxType(txType); + if (index > 0) { + await TransactionsPage.scrollToTheRow(index); + } + } +); + +Then( + /^I see (default - negative|green - positive) styling for transaction type: (Sent|Received|Self Transaction|Rewards|Delegation|Stake Key Registration|Stake Key De-Registration)$/, + async (styling: TransactionStyle, txType: TransactionType) => { + await transactionsPageAssert.assertSeeStylingForTxType(styling, txType); + } +); + Then(/^a skeleton (is|is not) displayed at the bottom of the page/, async (shouldBeDisplayed: 'is' | 'is not') => { await transactionsPageAssert.assertSeeSkeleton(shouldBeDisplayed === 'is'); }); diff --git a/packages/e2e-tests/src/types/transactionStyle.ts b/packages/e2e-tests/src/types/transactionStyle.ts new file mode 100644 index 000000000..d0a727037 --- /dev/null +++ b/packages/e2e-tests/src/types/transactionStyle.ts @@ -0,0 +1 @@ +export type TransactionStyle = 'default - negative' | 'green - positive'; diff --git a/packages/e2e-tests/src/types/transactionType.ts b/packages/e2e-tests/src/types/transactionType.ts new file mode 100644 index 000000000..58089e8a4 --- /dev/null +++ b/packages/e2e-tests/src/types/transactionType.ts @@ -0,0 +1,8 @@ +export type TransactionType = + | 'Sent' + | 'Received' + | 'Self Transaction' + | 'Rewards' + | 'Delegation' + | 'Stake Key Registration' + | 'Stake Key De-Registration '; diff --git a/packages/icons/raw/ada.component-transparent.svg b/packages/icons/raw/ada.component-transparent.svg new file mode 100644 index 000000000..4eabf49b4 --- /dev/null +++ b/packages/icons/raw/ada.component-transparent.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/packages/translation/src/lib/translations/browser-extension-wallet/en.json b/packages/translation/src/lib/translations/browser-extension-wallet/en.json index 0c3d05168..6e06722e0 100644 --- a/packages/translation/src/lib/translations/browser-extension-wallet/en.json +++ b/packages/translation/src/lib/translations/browser-extension-wallet/en.json @@ -127,6 +127,18 @@ "browserView.assets.startYourWeb3Journey": "Start your Web3 journey. Just add some digital assets to get started.", "browserView.assets.title": "Tokens", "browserView.assets.token": "Token", + "browserView.assets.topupWallet.buyButton.title": "On-Ramp Fiat-to-ADA powered by Banxa.", + "browserView.assets.topupWallet.buyButton.caption": "Buy ADA", + "browserView.assets.topupWallet.card.badge": "New", + "browserView.assets.topupWallet.card.title": "On-Ramp by Banxa", + "browserView.assets.topupWallet.disclaimer.short": "You will be redirected to Banxa’s website upon clicking “Buy ADA”", + "browserView.assets.topupWallet.disclaimer.full.part1": "If you click the “CONTINUE” button below, you will be redirected to Banxa's website and you also understand and acknowledge that Lace is not responsible for the services provided by Banxa (a third-party service provider) or on", + "browserView.assets.topupWallet.disclaimer.full.part2": "Please contact Banxa for all questions and support inquiries regarding services provided by Banxa or on", + "browserView.assets.topupWallet.disclaimer.full.banxaLinkCaption": "Banxa’s website", + "browserView.assets.topupWallet.modal.content": "", + "browserView.assets.topupWallet.modal.continue": "Continue", + "browserView.assets.topupWallet.modal.goBack": "Go Back", + "browserView.assets.topupWallet.modal.title": "You’re leaving Lace for Banxa", "browserView.assets.totalWalletBalance": "Total wallet balance", "browserView.assets.welcome": "Welcome!", "browserView.crypto.dashboard.adaBalance": "ADA Balance", diff --git a/packages/ui/src/design-system/buttons/call-to-action-button.css.ts b/packages/ui/src/design-system/buttons/call-to-action-button.css.ts index 749226fef..dc480cda1 100644 --- a/packages/ui/src/design-system/buttons/call-to-action-button.css.ts +++ b/packages/ui/src/design-system/buttons/call-to-action-button.css.ts @@ -44,5 +44,5 @@ export const container = style([ export const label = style({ // this was the only way to override the `recipe` used in `text.css.ts` https://github.com/vanilla-extract-css/vanilla-extract/discussions/466 - color: vars.colors.$buttons_cta_label_color, + color: `${vars.colors.$buttons_cta_label_color} !important`, }); diff --git a/packages/ui/src/design-system/buttons/call-to-action-button.tsx b/packages/ui/src/design-system/buttons/call-to-action-button.tsx index 7d456b656..5b02ad4ba 100644 --- a/packages/ui/src/design-system/buttons/call-to-action-button.tsx +++ b/packages/ui/src/design-system/buttons/call-to-action-button.tsx @@ -17,6 +17,7 @@ export const CallToAction = forwardRef( ref={forwardReference} className={{ container: classNames(cx.container, cx.button), + icon: cx.label, label: cx.label, }} /> diff --git a/packages/ui/src/design-system/dialog/dialog-action.component.tsx b/packages/ui/src/design-system/dialog/dialog-action.component.tsx index 97183adad..b021c0c5e 100644 --- a/packages/ui/src/design-system/dialog/dialog-action.component.tsx +++ b/packages/ui/src/design-system/dialog/dialog-action.component.tsx @@ -7,20 +7,29 @@ import * as Button from '../buttons'; export interface DialogActionProps { onClick: () => void; label: string; + disabled?: boolean; cancel?: boolean; + autoFocus?: boolean; } export const Action = ({ onClick, label, + disabled, cancel = false, + autoFocus = false, }: Readonly): JSX.Element => { const Wrapper = cancel ? AlertDialog.Cancel : AlertDialog.Action; const ActionButton = cancel ? Button.Secondary : Button.CallToAction; return ( - + ); }; diff --git a/packages/ui/src/design-system/profile-dropdown/profile-dropdown-wallet-card.component.tsx b/packages/ui/src/design-system/profile-dropdown/profile-dropdown-wallet-card.component.tsx index 767da5af7..c18a9af3b 100644 --- a/packages/ui/src/design-system/profile-dropdown/profile-dropdown-wallet-card.component.tsx +++ b/packages/ui/src/design-system/profile-dropdown/profile-dropdown-wallet-card.component.tsx @@ -46,7 +46,11 @@ export const WalletCard = ({ {profile === undefined ? ( ) : ( - + )} diff --git a/packages/ui/src/design-system/profile-picture/user-profile.component.tsx b/packages/ui/src/design-system/profile-picture/user-profile.component.tsx index e1e645e89..41f129189 100644 --- a/packages/ui/src/design-system/profile-picture/user-profile.component.tsx +++ b/packages/ui/src/design-system/profile-picture/user-profile.component.tsx @@ -13,6 +13,7 @@ interface Props { delayMs?: number; radius?: 'circle' | 'rounded'; background?: 'none'; + testId?: string; } interface FallbackText { @@ -29,6 +30,7 @@ export const UserProfile = ({ delayMs = 600, radius = 'circle', background, + testId, ...rest }: Readonly<Props & (FallbackImage | FallbackText)>): JSX.Element => ( <RadixUIAvatar.Root @@ -38,7 +40,12 @@ export const UserProfile = ({ [cx.noBackground]: background === 'none', })} > - <RadixUIAvatar.Image className={cx.image} src={imageSrc} alt={alt} /> + <RadixUIAvatar.Image + className={cx.image} + src={imageSrc} + alt={alt} + data-testid={testId} + /> <RadixUIAvatar.Fallback asChild delayMs={delayMs}> {'fallbackImage' in rest ? ( <img className={cx.image} src={rest.fallbackImage} alt={alt} />