diff --git a/manifest.json b/manifest.json index 95dabacad..bbc8dcd11 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "Pali Wallet", - "version": "2.0.14", + "version": "2.0.15", "icons": { "16": "assets/icons/favicon-16.png", "32": "assets/icons/favicon-32.png", diff --git a/package.json b/package.json index 894cf657c..195663e7d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "paliwallet", - "version": "2.0.14", + "version": "2.0.15", "description": "A Non-Custodial Crypto Wallet", "private": true, "repository": { @@ -48,7 +48,7 @@ "@babel/runtime": "^7.21.5", "@headlessui/react": "^1.6.0", "@heroicons/react": "^1.0.5", - "@pollum-io/sysweb3-keyring": "^1.0.477", + "@pollum-io/sysweb3-keyring": "^1.0.478", "@pollum-io/sysweb3-network": "^1.0.95", "@pollum-io/sysweb3-utils": "^1.1.232", "@reduxjs/toolkit": "^1.4.0", diff --git a/source/assets/locales/en.json b/source/assets/locales/en.json index c5dd68daa..20d8c988e 100644 --- a/source/assets/locales/en.json +++ b/source/assets/locales/en.json @@ -445,7 +445,7 @@ "formValue": "Form value", "tokenDecimals": "Token Decimals", "tokenSuccessfullyAdded": "Token successfully added!", - "wasSucessfullyAdded": "was successfully added to your wallet.", + "wasSuccessfullyAdded": "was successfully added to your wallet.", "verifyTheCurrentNetwork": "Verify the current network", "verifyTheCurrentNetworkMessage": "This token probably is not available in the current network. Verify the token network and try again.", "verifyTheCurrentNetworkLog": "Invalid contract address. Verify the current contract address.", diff --git a/source/assets/locales/es.json b/source/assets/locales/es.json index f1841d2b6..5ab97c336 100644 --- a/source/assets/locales/es.json +++ b/source/assets/locales/es.json @@ -445,7 +445,7 @@ "formValue": "Valor del formulario", "tokenDecimals": "Decimales del token", "tokenSuccessfullyAdded": "Token agregado correctamente!", - "wasSucessfullyAdded": "se ha agregado con éxito a su monedero.", + "wasSuccessfullyAdded": "se ha agregado con éxito a su monedero.", "verifyTheCurrentNetwork": "Verificar la red actual", "verifyTheCurrentNetworkMessage": "Este token probablemente no está disponible en la red actual. Verifique la red del token e inténtelo de nuevo.", "verifyTheCurrentNetworkLog": "Dirección de contrato no válida. Verifique la dirección de contrato actual.", diff --git a/source/assets/locales/pt-br.json b/source/assets/locales/pt-br.json index 6e61e3b73..143ac2e93 100644 --- a/source/assets/locales/pt-br.json +++ b/source/assets/locales/pt-br.json @@ -315,7 +315,7 @@ "formValue": "Form value", "tokenDecimals": "Token Decimals", "tokenSuccessfullyAdded": "Token successfully added!", - "wasSucessfullyAdded": "was successfully added to your wallet.", + "wasSuccessfullyAdded": "was successfully added to your wallet.", "verifyTheCurrentNetwork": "Verify the current network", "verifyTheCurrentNetworkMessage": "This token probably is not available in the current network. Verify the token network and try again.", "verifyTheCurrentNetworkLog": "Invalid contract address. Verify the current contract address.", diff --git a/source/components/Modal/WarningBaseModal.tsx b/source/components/Modal/WarningBaseModal.tsx index b9be41422..ca9ce4af9 100644 --- a/source/components/Modal/WarningBaseModal.tsx +++ b/source/components/Modal/WarningBaseModal.tsx @@ -142,7 +142,7 @@ export const ImportWalletWarning = ({ ); }; -export const TokenSuccessfulyAdded = ({ +export const TokenSuccessfullyAdded = ({ phraseOne, onClose, show = true, @@ -169,7 +169,7 @@ export const TokenSuccessfulyAdded = ({ ); -export const TimeSetSuccessfuly = ({ +export const TimeSetSuccessfully = ({ phraseOne, onClose, show = true, @@ -238,7 +238,6 @@ export const TxSuccessful = ({ title, }: IDefaultModal) => { const { t } = useTranslation(); - const navigate = useNavigate(); return ( @@ -253,7 +252,7 @@ export const TxSuccessful = ({ id="unlock-btn" type="submit" className="bg-white w-[22rem] h-10 text-brand-blue200 text-base mb-12 font-base font-medium rounded-2xl" - onClick={() => navigate('/home')} + onClick={onClose} > {t('buttons.ok')} diff --git a/source/pages/Home/Panel/components/Transactions/EVM/EvmList.tsx b/source/pages/Home/Panel/components/Transactions/EVM/EvmList.tsx index c9c9b7d88..3597901b9 100644 --- a/source/pages/Home/Panel/components/Transactions/EVM/EvmList.tsx +++ b/source/pages/Home/Panel/components/Transactions/EVM/EvmList.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; import { useTransactionsListConfig } from '../utils/useTransactionsInfos'; @@ -16,7 +16,6 @@ import { handleUpdateTransaction, isERC20Transfer, } from 'utils/transactions'; - export const EvmTransactionsList = ({ userTransactions, }: { @@ -30,7 +29,6 @@ export const EvmTransactionsList = ({ activeNetwork: { chainId }, isLastTxConfirmed, } = useSelector((state: RootState) => state.vault); - const { filteredTransactions, formatTimeStamp, @@ -43,23 +41,27 @@ export const EvmTransactionsList = ({ const [modalData, setModalData] = useState(); const [isOpenModal, setIsOpenModal] = useState(false); const [showModal, setShowModal] = useState(false); + const [groupedTransactions, setGroupedTransactions] = useState<{ + [date: string]: ITransactionInfoEvm[]; + }>({}); const { navigate } = useUtils(); const { getFiatAmount } = usePrice(); const { wallet } = getController(); - - const groupedTransactions = {}; - - filteredTransactions.forEach((tx) => { - const formattedDate = formatTimeStamp(tx.timestamp); - - if (!groupedTransactions[formattedDate]) { - groupedTransactions[formattedDate] = []; - } - - groupedTransactions[formattedDate].push(tx); - }); - - const currentAccount = accounts[activeAccount.type][activeAccount.id]; + useEffect(() => { + const grouped = {}; + filteredTransactions.forEach((tx) => { + const formattedDate = formatTimeStamp(tx.timestamp); + if (!grouped[formattedDate]) { + grouped[formattedDate] = []; + } + grouped[formattedDate].push(tx); + }); + setGroupedTransactions(grouped); + }, [filteredTransactions]); + const currentAccount = useMemo( + () => accounts[activeAccount.type][activeAccount.id], + [accounts, activeAccount] + ); const EvmTransactionsListComponent = ({ tx, }: { @@ -80,25 +82,20 @@ export const EvmTransactionsList = ({ ); } }; - const isTxCanceled = tx?.isCanceled === true; const isConfirmed = tx.confirmations > 0; const isErc20Tx = isERC20Transfer(tx as any); - const isTxSent = isBitcoinBased ? false : tx.from.toLowerCase() === currentAccount.address.toLowerCase(); - const tokenValue = !isConfirmed ? typeof tx.value === 'string' ? tx.value : Number(tx.value.hex) / 1e18 : Number(tx.value) / 1e18; - const finalTxValue = isErc20Tx ? Number(getERC20TransferValue(tx as any)) / 1e18 : tokenValue; - return (
@@ -114,7 +111,7 @@ export const EvmTransactionsList = ({
- {Number(finalTxValue).toFixed(4)}{' '} + {Number(finalTxValue).toFixed(4)} {getTokenSymbol(isErc20Tx, coinsList, tx)}
@@ -128,10 +125,7 @@ export const EvmTransactionsList = ({ src="/assets/icons/detailArrow.svg" onClick={() => navigate('/home/details', { - state: { - id: null, - hash: tx[txId], - }, + state: { id: null, hash: tx[txId] }, }) } /> @@ -144,7 +138,6 @@ export const EvmTransactionsList = ({
); }; - useEffect(() => { if (!currentAccount.transactions.ethereum?.[chainId]) { return; @@ -153,22 +146,18 @@ export const EvmTransactionsList = ({ const lastTx = currentAccount.transactions.ethereum[chainId][ lastIndex ] as IEvmTransaction; - if (isLastTxConfirmed?.[chainId]) { return; } - if (lastTx?.confirmations === 0) { wallet.setIsLastTxConfirmed(chainId, false); return; } - if (lastTx?.confirmations > 0 && !isLastTxConfirmed?.[chainId]) { setShowModal(true); wallet.setIsLastTxConfirmed(chainId, true); } }, [currentAccount]); - return ( <> { {t('settings.setAutoLockTime')}

- { setConfirmed(false); diff --git a/source/pages/SwitchNetwork/NetworkInfo.ts b/source/pages/SwitchNetwork/NetworkInfo.ts index f5bcf8d70..d3cb7d89f 100644 --- a/source/pages/SwitchNetwork/NetworkInfo.ts +++ b/source/pages/SwitchNetwork/NetworkInfo.ts @@ -25,19 +25,22 @@ interface INetworkInfo { const PINK_COLOR = 'text-brand-deepPink100'; const BLUE_COLOR = 'text-brand-blue200'; -export const useNetworkInfo = (setedNetwork?: string): INetworkInfo => { - const isBitcoinBased = useSelector( - (state: RootState) => state.vault.isBitcoinBased - ); - const networks = useSelector((state: RootState) => state.vault.networks); - +export const useNetworkInfo = ({ + network, + isBitcoinBased, + networks, +}: { + isBitcoinBased?: boolean; + network?: string; + networks: RootState['vault']['networks']; +}): INetworkInfo => { const filteredNetworks = useMemo(() => { - if (setedNetwork !== '') { - return setedNetwork === 'EVM' + if (network !== '') { + return network === 'EVM' ? Object.values(networks.syscoin) : Object.values(networks.ethereum); } - }, [setedNetwork, isBitcoinBased, networks]); + }, [network, isBitcoinBased, networks]); const utxoNetwork: INetworkInfo = { connectedNetwork: NetworkType.UTXO, @@ -65,8 +68,8 @@ export const useNetworkInfo = (setedNetwork?: string): INetworkInfo => { let value: any; - if (setedNetwork) { - if (setedNetwork === 'EVM') { + if (network) { + if (network === 'EVM') { value = otherNetworkInfo; } else { value = utxoNetwork; diff --git a/source/pages/SwitchNetwork/NetworkList.tsx b/source/pages/SwitchNetwork/NetworkList.tsx index 7d6641dd1..e7e3ac35f 100644 --- a/source/pages/SwitchNetwork/NetworkList.tsx +++ b/source/pages/SwitchNetwork/NetworkList.tsx @@ -1,5 +1,5 @@ import { uniqueId } from 'lodash'; -import React, { useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { useSelector } from 'react-redux'; import { INetwork } from '@pollum-io/sysweb3-network'; @@ -14,7 +14,9 @@ import { useNetworkInfo } from './NetworkInfo'; export const NetworkList = ({ isChanging }: { isChanging: boolean }) => { const { wallet } = getController(); - const { isBitcoinBased } = useSelector((state: RootState) => state.vault); + const { isBitcoinBased, networks } = useSelector( + (state: RootState) => state.vault + ); const [selectCurrentNetwork, setSelectCurrentNetwork] = useState({ current: null, chain: '', @@ -29,23 +31,35 @@ export const NetworkList = ({ isChanging }: { isChanging: boolean }) => { selectedNetworkText, leftLogo, rightLogo, - } = useNetworkInfo(); - const chainName = isBitcoinBased ? 'ethereum' : 'syscoin'; - - const networks = useSelector((state: RootState) => state.vault.networks); - - let newNetworks; + } = useNetworkInfo({ isBitcoinBased, networks }); - isBitcoinBased - ? (newNetworks = Object.values(networks.ethereum)) - : (newNetworks = Object.values(networks.syscoin)); + const chainName = useMemo( + () => (isBitcoinBased ? 'ethereum' : 'syscoin'), + [isBitcoinBased] + ); - const testnetNetworks = newNetworks.filter((obj) => obj?.isTestnet === true); + const newNetworks = useMemo( + () => + isBitcoinBased + ? Object.values(networks.ethereum) + : Object.values(networks.syscoin), + [isBitcoinBased] + ); //todo: change name - let mainetNetworks = newNetworks.filter((obj) => obj?.isTestnet !== true); + const testnetNetworks = useMemo( + () => newNetworks.filter((obj) => obj?.isTestnet), + [newNetworks] + ); - mainetNetworks = mainetNetworks.sort( - (a, b) => getChainIdPriority(a.chainId) - getChainIdPriority(b.chainId) + const mainnetNetworks = useMemo( + () => + newNetworks + .filter((obj) => !obj?.isTestnet) + .sort( + (a, b) => + getChainIdPriority(a.chainId) - getChainIdPriority(b.chainId) + ), + [] ); const handleChangeNetwork = async (network: INetwork, chain: string) => { @@ -97,7 +111,7 @@ export const NetworkList = ({ isChanging }: { isChanging: boolean }) => {

{selectedNetworkText}

- {mainetNetworks.map((currentNetwork: INetwork) => ( + {mainnetNetworks.map((currentNetwork: INetwork) => (
{ const { state }: { state: any } = useLocation(); const { t } = useTranslation(); - const activeNetwork = useSelector( - (state: RootState) => state.vault.activeNetwork + const { isBitcoinBased, activeNetwork, networks } = useSelector( + (rootState: RootState) => rootState.vault ); const { connectedNetwork, networkThatNeedsChanging, connectedColor, networkNeedsChangingColor, - } = useNetworkInfo(); + } = useNetworkInfo({ isBitcoinBased, networks }); const networkLabel = useMemo( () => ( diff --git a/source/pages/Tokens/CustomToken.tsx b/source/pages/Tokens/CustomToken.tsx index 3e75addeb..f5e1fb325 100644 --- a/source/pages/Tokens/CustomToken.tsx +++ b/source/pages/Tokens/CustomToken.tsx @@ -12,7 +12,7 @@ import { } from '@pollum-io/sysweb3-utils'; import { Card, NeutralButton } from 'components/index'; -import { TokenSuccessfulyAdded } from 'components/Modal/WarningBaseModal'; +import { TokenSuccessfullyAdded } from 'components/Modal/WarningBaseModal'; import { useUtils } from 'hooks/index'; import { RootState } from 'state/store'; import { IAddCustomTokenMetadataInfos, ITokenEthProps } from 'types/tokens'; @@ -630,9 +630,10 @@ export const CustomToken = (props: ICustomTokenComponentProps) => {
@@ -662,13 +663,14 @@ export const CustomToken = (props: ICustomTokenComponentProps) => { {added && ( - navigate('/home')} + buttonText={t('settings.gotIt')} /> )} diff --git a/source/pages/Tokens/ImportToken.tsx b/source/pages/Tokens/ImportToken.tsx index 3900a92c6..ab1eeb637 100644 --- a/source/pages/Tokens/ImportToken.tsx +++ b/source/pages/Tokens/ImportToken.tsx @@ -155,7 +155,7 @@ export const ImportToken: FC = () => { show={added} title={t('tokens.tokenSuccessfullyAdded')} description={`${selected.tokenSymbol} ${t( - 'tokens.wasSucessfullyAdded' + 'tokens.wasSuccessfullyAdded' )}`} onClose={() => navigate('/home')} /> diff --git a/source/pages/Tokens/SyscoinImport.tsx b/source/pages/Tokens/SyscoinImport.tsx index 1802d5f36..558f8ae52 100644 --- a/source/pages/Tokens/SyscoinImport.tsx +++ b/source/pages/Tokens/SyscoinImport.tsx @@ -9,7 +9,7 @@ import { useSelector } from 'react-redux'; import { getAsset } from '@pollum-io/sysweb3-utils'; import { ErrorModal, NeutralButton } from 'components/index'; -import { TokenSuccessfulyAdded } from 'components/Modal/WarningBaseModal'; +import { TokenSuccessfullyAdded } from 'components/Modal/WarningBaseModal'; import { useUtils } from 'hooks/index'; import { RootState } from 'state/store'; import { getController } from 'utils/browser'; @@ -117,9 +117,10 @@ export const SyscoinImportToken = () => {
@@ -138,13 +139,14 @@ export const SyscoinImportToken = () => { {added && ( - navigate('/home')} show={added} + buttonText={t('settings.gotIt')} /> )} diff --git a/source/pages/Transactions/Sign.tsx b/source/pages/Transactions/Sign.tsx index 19bb5318a..ccc40d337 100644 --- a/source/pages/Transactions/Sign.tsx +++ b/source/pages/Transactions/Sign.tsx @@ -3,15 +3,8 @@ import { useTranslation } from 'react-i18next'; import { useSelector } from 'react-redux'; import { browser } from 'webextension-polyfill-ts'; -import { - Button, - DefaultModal, - ErrorModal, - Layout, - PrimaryButton, - SecondaryButton, -} from 'components/index'; -import { TokenSuccessfulyAdded } from 'components/Modal/WarningBaseModal'; +import { Button, DefaultModal, ErrorModal, Layout } from 'components/index'; +import { TokenSuccessfullyAdded } from 'components/Modal/WarningBaseModal'; import { useQueryData } from 'hooks/index'; import { RootState } from 'state/store'; import { dispatchBackgroundEvent, getController } from 'utils/browser'; @@ -64,7 +57,7 @@ const Sign: React.FC = ({ send = false }) => { return ( - { port.postMessage({ id: message.id, data: response }); } catch (error: any) { console.error(error); - port.postMessage({ id: message.id, data: { error: error } }); //This was altered for better ethereum compability TODO: check on syscoin contentScript side + port.postMessage({ id: message.id, data: { error: error } }); //This was altered for better ethereum compatibility TODO: check on syscoin contentScript side } }; diff --git a/source/scripts/Background/controllers/message-handler/requests.ts b/source/scripts/Background/controllers/message-handler/requests.ts index d6d424e5c..622f4b9a5 100644 --- a/source/scripts/Background/controllers/message-handler/requests.ts +++ b/source/scripts/Background/controllers/message-handler/requests.ts @@ -8,6 +8,7 @@ import { SysProvider } from 'scripts/Provider/SysProvider'; import store from 'state/store'; import { getController } from 'utils/browser'; import cleanErrorStack from 'utils/cleanErrorStack'; +import { areStringsPresent } from 'utils/format'; import { networkChain } from 'utils/network'; import { popupPromise } from './popup-promise'; @@ -25,6 +26,8 @@ export const methodRequest = async ( ) => { const { dapp, wallet } = window.controller; const controller = getController(); + const hybridDapps = ['bridge']; // create this array to be populated with hybrid dapps. + const isHybridDapp = areStringsPresent(host, hybridDapps); const [prefix, methodName] = data.method.split('_'); const { activeAccount, isBitcoinBased, isNetworkChanging, accounts } = store.getState().vault; @@ -56,7 +59,7 @@ export const methodRequest = async ( console.error( 'It is not possible to interact with content scripts using Trezor Wallet. Please switch to a different account and try again.' ); - //Todo: we're throwing arbitrary error codes here, later it would be good to check the avaiability of this errors codes and create a UTXO(bitcoin) json error standard and submit as a BIP; + //Todo: we're throwing arbitrary error codes here, later it would be good to check the availability of this errors codes and create a UTXO(bitcoin) json error standard and submit as a BIP; throw ethErrors.provider.custom({ code: 4874, message: @@ -71,7 +74,7 @@ export const methodRequest = async ( if (prefix === 'eth' && methodName === 'requestAccounts') { try { - return await enable(host, undefined, undefined, false); + return await enable(host, undefined, undefined, false, isHybridDapp); } catch (error) { await popupPromise({ host, @@ -80,12 +83,12 @@ export const methodRequest = async ( data: {}, }); - return await enable(host, undefined, undefined, false); + return await enable(host, undefined, undefined, false, isHybridDapp); } } if (prefix === 'sys' && methodName === 'requestAccounts') { try { - return await enable(host, undefined, undefined, true); + return await enable(host, undefined, undefined, true, isHybridDapp); } catch (error) { if (error.message === 'Connected to Ethereum based chain') { await popupPromise({ @@ -95,7 +98,7 @@ export const methodRequest = async ( data: { network: data.network }, }); - return await enable(host, undefined, undefined, true); + return await enable(host, undefined, undefined, true, isHybridDapp); } } } @@ -385,7 +388,7 @@ export const methodRequest = async ( return resp; } else if (prefix === 'sys' && !isBitcoinBased) { throw cleanErrorStack(ethErrors.rpc.internal()); - } else if (prefix === 'eth' && isBitcoinBased) { + } else if (prefix === 'eth' && isBitcoinBased && !isHybridDapp) { throw cleanErrorStack( ethErrors.provider.unauthorized( 'Method only available when connected on EVM chains' @@ -396,31 +399,31 @@ export const methodRequest = async ( const provider = SysProvider(host); const method = provider[methodName]; - if (!method) throw cleanErrorStack(ethErrors.rpc.methodNotFound()); - - if (data.params) return await method(...data.params); - - return await method(); + if (method) { + if (data.params) return await method(...data.params); + return await method(); + } }; export const enable = async ( host: string, chain: string, chainId: number, - isSyscoinDapp = false + isSyscoinDapp = false, + isHybridDapp = true ) => { const { isBitcoinBased } = store.getState().vault; const { dapp, wallet } = window.controller; const { isOpen: isPopupOpen } = JSON.parse( window.localStorage.getItem('isPopupOpen') ); - if (!isSyscoinDapp && isBitcoinBased) { + if (!isSyscoinDapp && isBitcoinBased && !isHybridDapp) { throw ethErrors.provider.custom({ code: 4101, message: 'Connected to Bitcoin based chain', data: { code: 4101, message: 'Connected to Bitcoin based chain' }, }); - } else if (isSyscoinDapp && !isBitcoinBased) { + } else if (isSyscoinDapp && !isBitcoinBased && !isHybridDapp) { throw ethErrors.provider.custom({ code: 4101, message: 'Connected to Ethereum based chain', diff --git a/source/utils/format.ts b/source/utils/format.ts index 2aa9e87b3..84660cd41 100644 --- a/source/utils/format.ts +++ b/source/utils/format.ts @@ -144,3 +144,10 @@ export const camelCaseToText = (input: string) => { // this regex splits the string without removing the delimiters return input.split(/(?=[A-Z])/).join(' '); }; + +export const areStringsPresent = ( + strToCheck: string, + stringsArray: string[] +): boolean => + // Check if any string from stringsArray is present in strToCheck + stringsArray.some((subString) => strToCheck.includes(subString)); diff --git a/yarn.lock b/yarn.lock index 382c6630f..81d0f2286 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2273,10 +2273,10 @@ resolved "https://registry.yarnpkg.com/@pollum-io/sysweb3-core/-/sysweb3-core-1.0.26.tgz#57a1fd60942b6d2261fb74f73807698205ecb344" integrity sha512-6NG2s0PLEMVQyMQnC8voZOKWh+MAp6SX9B4Dseg79Xtfi/flWp2FV/uVg7WzY9C3bTpHJ+mqtLWeWRgG63dQ/w== -"@pollum-io/sysweb3-keyring@^1.0.477": - version "1.0.477" - resolved "https://registry.yarnpkg.com/@pollum-io/sysweb3-keyring/-/sysweb3-keyring-1.0.477.tgz#831c4ede9ac9ff7e67f2d38c07eeb449f4149323" - integrity sha512-lAZpHRRyfpazPaPqVQk07BS9QO9wuap2sLbf98683P2BpCVv8FPZY4AK2Nsg11QQH0QtgR/sAv2v+0rjGA3AdQ== +"@pollum-io/sysweb3-keyring@^1.0.478": + version "1.0.478" + resolved "https://registry.yarnpkg.com/@pollum-io/sysweb3-keyring/-/sysweb3-keyring-1.0.478.tgz#c1b9c85c29c8266bb0ed0ec1b00f73a988cb34a5" + integrity sha512-JYvQgHDVK5hxYf2touwyMYaQh6ddpf84oPDwduN54GM043O8ClOa6VWo1oQM9AHGbhnek1J2s3Z6Tggt7SOkgg== dependencies: "@bitcoinerlab/descriptors" "^2.0.1" "@bitcoinerlab/secp256k1" "^1.0.5"