diff --git a/.envrc b/.envrc new file mode 100644 index 000000000..76e15a514 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +REACT_APP_SEED_PEACE_GLOBE \ No newline at end of file diff --git a/palette.js b/palette.js index 6587f5043..1f60e6a22 100644 --- a/palette.js +++ b/palette.js @@ -109,7 +109,7 @@ module.exports = { }, alpha: { - whiteAlpha300: '#FFFFFF29', + whiteAlpha300: 'rgba(255, 255, 255, 0.16)', whiteAlpha200: 'rgba(255, 255, 255, 0.08)', }, diff --git a/source/assets/icons/ArrowDown.svg b/source/assets/icons/ArrowDown.svg new file mode 100644 index 000000000..f1efec142 --- /dev/null +++ b/source/assets/icons/ArrowDown.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/source/assets/icons/info.svg b/source/assets/icons/info.svg new file mode 100644 index 000000000..9e1b90360 --- /dev/null +++ b/source/assets/icons/info.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/source/assets/images/paliLogoWhiteSmall.svg b/source/assets/images/paliLogoWhiteSmall.svg new file mode 100644 index 000000000..a013f0cf0 --- /dev/null +++ b/source/assets/images/paliLogoWhiteSmall.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/source/assets/styles/custom-autolock-input.css b/source/assets/styles/custom-autolock-input.css index d2515416e..bd3c1a9ef 100644 --- a/source/assets/styles/custom-autolock-input.css +++ b/source/assets/styles/custom-autolock-input.css @@ -1,6 +1,6 @@ .custom-autolock-input { display: flex; - width: 352px !important; + width: 352px; height: 40px; padding: 11px 73px; align-items: center; @@ -9,3 +9,16 @@ background-color: #07152a !important; font-size: 12px; } + +.custom-gas-input { + display: flex; + width: 352px; + height: 40px; + padding: 11px 20px; + flex-direction: column; + justify-content: center; + align-items: flex-start; + border-radius: 100px; + border: 1px solid rgba(255, 255, 255, 0.16); + background: #162742; +} diff --git a/source/assets/styles/custom-import-token-input.css b/source/assets/styles/custom-import-token-input.css new file mode 100644 index 000000000..1beaddd53 --- /dev/null +++ b/source/assets/styles/custom-import-token-input.css @@ -0,0 +1,42 @@ +.custom-import-input .ant-input { + display: flex; + width: 352px; + height: 40px; + padding: 12px 55px 12px 15px; + align-items: center; + border-radius: 100px; + border: 1px solid rgba(255, 255, 255, 0.16); + background-color: #07152a !important; + font-size: 12px; +} + +.custom-import-input .ant-input-suffix .anticon-close-circle { + content: url('../icons/errorIcon.svg'); + position: absolute; + top: 55%; + right: 28px; + transform: translateY(-50%); + cursor: pointer; + font-size: 14px; + line-height: 14px; +} + +.custom-import-input .ant-input-suffix .anticon-check-circle { + content: url('../icons/successIcon.svg'); + position: absolute; + top: 53%; + right: 28px; + transform: translateY(-50%); + cursor: pointer; + font-size: 14px; + line-height: 14px; +} + +.custom-import-input .ant-input-suffix .anticon-loading { + position: absolute; + top: 40%; + right: 28px; + cursor: pointer; + font-size: 14px; + line-height: 14px; +} diff --git a/source/assets/styles/custom-receive-input.css b/source/assets/styles/custom-receive-input.css new file mode 100644 index 000000000..9a2e2e0b7 --- /dev/null +++ b/source/assets/styles/custom-receive-input.css @@ -0,0 +1,33 @@ +.custom-receive-input { + display: flex; + width: 352px; + height: 40px; + align-items: center; + border-radius: 100px; + border: 1px solid rgba(255, 255, 255, 0.16); + background-color: #07152a; + font-size: 12px; + padding: 12px 55px 12px 15px; +} + +.custom-receive-input .ant-input-suffix .anticon-close-circle { + content: url('../icons/errorIcon.svg'); + position: absolute; + top: 55%; + right: 80px; + transform: translateY(-50%); + cursor: pointer; + font-size: 14px; + line-height: 14px; +} + +.custom-receive-input .ant-input-suffix .anticon-check-circle { + content: url('../icons/successIcon.svg'); + position: absolute; + top: 53%; + right: 40px; + transform: translateY(-50%); + cursor: pointer; + font-size: 14px; + line-height: 14px; +} diff --git a/source/assets/styles/custom-send-utxo-input.css b/source/assets/styles/custom-send-utxo-input.css new file mode 100644 index 000000000..cfb55ff99 --- /dev/null +++ b/source/assets/styles/custom-send-utxo-input.css @@ -0,0 +1,78 @@ +.sender-custom-input .ant-input { + display: flex; + width: 352px; + height: 40px; + padding: 11px 20px; + border-radius: 100px; + border: 1px solid rgba(255, 255, 255, 0.16); + background-color: #07152a !important; + font-size: 12px; +} + +#with-max-button, +.sender-custom-input .ant-input { + width: 244px; + padding: 10px 70px; +} + +#fee-input, +.sender-custom-input .ant-input { + width: 352px; + color: #fff !important; + padding: 11px 20px; +} + +.sender-custom-input .ant-input-suffix .anticon-close-circle { + content: url('../icons/errorIcon.svg'); + position: absolute; + top: 18.5rem; + right: 45px; + transform: translateY(-50%); + cursor: pointer; + font-size: 14px; + line-height: 14px; +} + +.sender-custom-input .ant-input-suffix .anticon-check-circle { + content: url('../icons/successIcon.svg'); + position: absolute; + top: 18.5rem; + right: 45px; + transform: translateY(-50%); + cursor: pointer; + font-size: 14px; + line-height: 14px; +} + +.value-custom-input .ant-input { + display: flex; + width: 244px; + height: 40px; + padding: 11px 20px; + border-radius: 100px; + border: 1px solid rgba(255, 255, 255, 0.16); + background-color: #07152a !important; + font-size: 12px; +} + +.value-custom-input .ant-input-suffix .anticon-close-circle { + content: url('../icons/errorIcon.svg'); + position: absolute; + top: 1.2rem; + right: 23px; + transform: translateY(-50%); + cursor: pointer; + font-size: 14px; + line-height: 14px; +} + +.value-custom-input .ant-input-suffix .anticon-check-circle { + content: url('../icons/successIcon.svg'); + position: absolute; + top: 1.2rem; + right: 23px; + transform: translateY(-50%); + cursor: pointer; + font-size: 14px; + line-height: 14px; +} diff --git a/source/components/Fee/Fee.tsx b/source/components/Fee/Fee.tsx index 783efabf1..5d0f24c0c 100755 --- a/source/components/Fee/Fee.tsx +++ b/source/components/Fee/Fee.tsx @@ -2,25 +2,23 @@ import { Form, Input } from 'antd'; import React from 'react'; import { useTranslation } from 'react-i18next'; -import { Icon, Tooltip } from '..'; +import { Tooltip } from '..'; export const Fee = ({ recommend, disabled, form, + fiatValue, }: { disabled: boolean; + fiatValue?: string; form: any; recommend?: number; }) => { const { t } = useTranslation(); return ( -
- - - - +
- - form.setFieldsValue({ fee: event.target.value }) - } - /> +
+ + form.setFieldsValue({ fee: event.target.value }) + } + /> +

+ + {'≈ '} + {fiatValue} + +

+
diff --git a/source/components/Header/AccountHeader.tsx b/source/components/Header/AccountHeader.tsx index a2e943189..a46a342d4 100644 --- a/source/components/Header/AccountHeader.tsx +++ b/source/components/Header/AccountHeader.tsx @@ -414,6 +414,7 @@ export const AccountHeader: React.FC = () => { const controller = getController(); const isLedger = activeAccount.type === KeyringAccountType.Ledger; const url = browser.runtime.getURL('app.html'); + useEffect(() => { const placeholder = document.querySelector('.add-identicon'); if (!placeholder) return; diff --git a/source/components/Icon/Icon.tsx b/source/components/Icon/Icon.tsx index 85fd66107..87d6bbd75 100755 --- a/source/components/Icon/Icon.tsx +++ b/source/components/Icon/Icon.tsx @@ -57,6 +57,7 @@ const icons = { const svgIcons = { ArrowUpBoldIcon: '../../assets/icons/ArrowUp.svg', ArrowDownLoad: '../../assets/icons/ArrowDownLoad.svg', + ArrowDown: '/assets/icons/ArrowDown.svg', ArrowLeft: '../../assets/icons/ArrowLeft.svg', Close: '../../assets/icons/closeBigger.svg', EditTx: '/assets/icons/editTx.svg', @@ -65,6 +66,7 @@ const svgIcons = { Trash: '../../assets/icons/trashIcon.svg', warning: '../../assets/icons/yellowWarn.svg', Copy: '/assets/icons/copy.svg', + Info: '/assets/icons/info.svg', }; interface IIcon { diff --git a/source/components/Modal/EditFeeModalBase.tsx b/source/components/Modal/EditFeeModalBase.tsx new file mode 100644 index 000000000..0196f81f1 --- /dev/null +++ b/source/components/Modal/EditFeeModalBase.tsx @@ -0,0 +1,58 @@ +import { Dialog, Transition } from '@headlessui/react'; +import React, { Fragment, ReactNode } from 'react'; + +interface IModal { + children: ReactNode; + className?: string; + onClose?: () => any; + show?: boolean; +} + +export const EditFeeModalBase = ({ + children, + className = '', + onClose, + show = true, +}: IModal) => ( + + { + if (onClose) onClose(); + }} + > +
+ +
+ + + + + + + + {children} + +
+
+
+); diff --git a/source/components/Modal/Modal.tsx b/source/components/Modal/Modal.tsx index ab67ab635..5fa349ad2 100755 --- a/source/components/Modal/Modal.tsx +++ b/source/components/Modal/Modal.tsx @@ -44,7 +44,7 @@ export const Modal = ({ { if (onClose) onClose(); }} diff --git a/source/components/Modal/WarningBaseModal.tsx b/source/components/Modal/WarningBaseModal.tsx index 901adce4f..ef7680b9b 100644 --- a/source/components/Modal/WarningBaseModal.tsx +++ b/source/components/Modal/WarningBaseModal.tsx @@ -148,7 +148,34 @@ export const TokenSuccessfulyAdded = ({ show = true, title, buttonText, +}: IDefaultModal) => ( + +
+
+

{title}

+
+
+

{phraseOne}

+
+ +
+
+); + +export const TimeSetSuccessfuly = ({ + phraseOne, + onClose, + show = true, + title, }: IDefaultModal) => { + const { t } = useTranslation(); const navigate = useNavigate(); return ( @@ -164,16 +191,16 @@ export const TokenSuccessfulyAdded = ({ 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={onClose} + onClick={() => navigate('/home')} > - {buttonText} + {t('buttons.ok')}
); }; -export const TimeSetSuccessfuly = ({ +export const SignatureRequestSuccessfullySubmit = ({ phraseOne, onClose, show = true, @@ -204,7 +231,7 @@ export const TimeSetSuccessfuly = ({ ); }; -export const SignatureRequestSuccessfullySubmit = ({ +export const TxSuccessful = ({ phraseOne, onClose, show = true, diff --git a/source/pages/App/index.tsx b/source/pages/App/index.tsx index fe19792dd..a2bff3d87 100755 --- a/source/pages/App/index.tsx +++ b/source/pages/App/index.tsx @@ -4,6 +4,9 @@ import 'assets/styles/custom-input-search.css'; import 'assets/styles/custom-checkbox.css'; import 'assets/styles/custom-form-inputs-styles.css'; import 'assets/styles/custom-autolock-input.css'; +import 'assets/styles/custom-receive-input.css'; +import 'assets/styles/custom-import-token-input.css'; +import 'assets/styles/custom-send-utxo-input.css'; import 'assets/fonts/index.css'; import React from 'react'; diff --git a/source/pages/External/index.tsx b/source/pages/External/index.tsx index 3b3bbaec6..6b98f0010 100644 --- a/source/pages/External/index.tsx +++ b/source/pages/External/index.tsx @@ -14,7 +14,10 @@ import 'assets/styles/custom-input-search.css'; import 'assets/styles/custom-checkbox.css'; import 'assets/styles/custom-form-inputs-styles.css'; import 'assets/styles/custom-autolock-input.css'; +import 'assets/styles/custom-receive-input.css'; +import 'assets/styles/custom-import-token-input.css'; import 'assets/fonts/index.css'; +import 'assets/styles/custom-send-utxo-input.css'; import { log } from 'utils/index'; import External from './External'; diff --git a/source/pages/Receive/Receive.tsx b/source/pages/Receive/Receive.tsx index 7b88a7aa8..9a0195ff3 100755 --- a/source/pages/Receive/Receive.tsx +++ b/source/pages/Receive/Receive.tsx @@ -7,7 +7,6 @@ import { Layout, NeutralButton } from 'components/index'; import { LoadingComponent } from 'components/Loading'; import { useUtils } from 'hooks/index'; import { RootState } from 'state/store'; -import { ellipsis } from 'utils/index'; export const Receive = () => { const { useCopyClipboard, alert } = useUtils(); @@ -37,31 +36,37 @@ export const Receive = () => { id="receiveSYS-title" > {activeAccount.address ? ( -
+
- -

- {ellipsis(activeAccount.address, 4, 10)} -

+
+

+ {activeAccount.address} +

+
copyText(activeAccount.address)} > {t('buttons.copy')} diff --git a/source/pages/Send/Approve.tsx b/source/pages/Send/Approve.tsx index 105a8641c..0ea4e0040 100644 --- a/source/pages/Send/Approve.tsx +++ b/source/pages/Send/Approve.tsx @@ -32,7 +32,7 @@ import { fetchGasAndDecodeFunction } from 'utils/fetchGasAndDecodeFunction'; import { verifyZerosInBalanceAndFormat, ellipsis, logError } from 'utils/index'; import { EditApprovedAllowanceValueModal } from './EditApprovedAllowanceValueModal'; -import { EditPriorityModal } from './EditPriorityModal'; +import { EditPriorityModal } from './EditPriority'; export const ApproveTransactionComponent = () => { const { wallet } = getController(); @@ -343,12 +343,6 @@ export const ApproveTransactionComponent = () => { }} /> - setHaveError(false)} - /> { setHaveError={setHaveError} fee={fee} /> + + setHaveError(false)} + /> { const { wallet, callGetLatestUpdateForAccount } = getController(); @@ -830,10 +831,10 @@ export const SendConfirm = () => { return ( - { wallet.sendAndSaveTransaction(confirmedTx); wallet.setIsLastTxConfirmed(activeNetwork.chainId, false); @@ -841,6 +842,15 @@ export const SendConfirm = () => { }} /> + + { description={t('send.changeFields')} onClose={() => setHaveError(false)} /> - - {Boolean( !isBitcoinBased && basicTxValues && fee && isEIP1559Compatible ) || @@ -893,7 +894,7 @@ export const SendConfirm = () => {

) : ( -
+
{
)} -
-

+

+

{t('send.from')} {

-

+

+

{t('send.to')} {

- -
-

+

+
+

{t('send.estimatedGasFee')} {isBitcoinBased @@ -970,21 +972,21 @@ export const SendConfirm = () => { {!isBitcoinBased && !basicTxValues.token?.isNft ? !isBitcoinBased && isEIP1559Compatible && ( -

setIsOpenEditFeeModal(true)} > {' '} -
+ ) : null}
- -

+

+

{!basicTxValues.token?.isNft ? ( <> Total ({t('send.amountAndFee')}) diff --git a/source/pages/Send/EditPriorityModal.tsx b/source/pages/Send/EditPriority.tsx similarity index 56% rename from source/pages/Send/EditPriorityModal.tsx rename to source/pages/Send/EditPriority.tsx index 042ab5357..13a7e82bb 100644 --- a/source/pages/Send/EditPriorityModal.tsx +++ b/source/pages/Send/EditPriority.tsx @@ -1,8 +1,9 @@ -import { Form, Input } from 'antd'; +import { Form } from 'antd'; import React, { useEffect, useState } from 'react'; import { useTranslation } from 'react-i18next'; -import { Modal, NeutralButton } from 'components/index'; +import { Button } from 'components/index'; +import { EditFeeModalBase } from 'components/Modal/EditFeeModalBase'; import { ICustomFeeParams, IFeeState } from 'types/transactions'; import removeScientificNotation from 'utils/removeScientificNotation'; @@ -189,7 +190,7 @@ export const EditPriorityModal = (props: IEditPriorityModalProps) => { }, [priority, fee, showModal, gasPrice, isSendLegacyTransaction]); return ( - { setCustomFee((prevState) => ({ @@ -202,114 +203,156 @@ export const EditPriorityModal = (props: IEditPriorityModalProps) => { setIsOpen(false); }} > -

+
-

- {t('send.editFee')} -

- - setPriority(value)} - /> - -
-
- - {t('send.gasLimit')} - - ({ - validator(_, value) { - if (value > 1000) { - return Promise.resolve(); - } - - return Promise.reject(); - }, - }), - ]} - initialValue={fee?.gasLimit} - > - - setCustomFee((prevState) => ({ - ...prevState, - isCustom: true, - gasLimit: +e.target.value, - })) - } - /> - +
+

+ {t('send.editFee')} +

+
+
+
+ setPriority(value)} + />
+ +
+

{t('send.gasLimit')}

+ ({ + validator(_, value) { + if (value > 1000) { + return Promise.resolve(); + } - {!isSendLegacyTransaction ? ( - <> -
- - {t('send.maxPriority')} (GWEI) - - ({ - validator(_, value) { - if (value < customFee.maxFeePerGas) { - return Promise.resolve(); - } + }), + ]} + initialValue={fee?.gasLimit} + > + + setCustomFee((prevState) => ({ + ...prevState, + isCustom: true, + gasLimit: +e.target.value, + })) + } + /> + +
- return Promise.reject(); + {!isSendLegacyTransaction ? ( + <> +
+

+ {t('send.maxPriority')} (GWEI) +

+ - - setCustomFee((prevState) => ({ - ...prevState, - isCustom: true, - maxPriorityFeePerGas: +e.target.value, - })) - } - /> - -
+ () => ({ + validator(_, value) { + if (value < customFee.maxFeePerGas) { + return Promise.resolve(); + } + + return Promise.reject(); + }, + }), + ]} + > + + setCustomFee((prevState) => ({ + ...prevState, + isCustom: true, + maxPriorityFeePerGas: +e.target.value, + })) + } + /> +
+
+
+

+ {t('send.maxFee')} (GWEI) +

+ ({ + validator(_, value) { + if (value <= 30 && value >= 1) { + return Promise.resolve(); + } + + return Promise.reject(); + }, + }), + ]} + > + {/* // base fee + priority fee */} + + setCustomFee((prevState) => ({ + ...prevState, + isCustom: true, + maxFeePerGas: +e.target.value, + })) + } + /> + +
+ + ) : (
- - {t('send.maxFee')} (GWEI) - +

+ {t('send.gasPrice')} (GWEI) +

{ }, () => ({ validator(_, value) { - if (value <= 30 && value >= 1) { + if (value < customFee.gasPrice) { return Promise.resolve(); } @@ -328,75 +371,44 @@ export const EditPriorityModal = (props: IEditPriorityModalProps) => { }), ]} > - {/* // base fee + priority fee */} - setCustomFee((prevState) => ({ ...prevState, isCustom: true, - maxFeePerGas: +e.target.value, + gasPrice: +e.target.value, })) } />
- - ) : ( -
- - {t('send.gasPrice')} (GWEI) - - ({ - validator(_, value) { - if (value < customFee.gasPrice) { - return Promise.resolve(); - } - - return Promise.reject(); - }, - }), - ]} - > - - setCustomFee((prevState) => ({ - ...prevState, - isCustom: true, - gasPrice: +e.target.value, - })) - } - /> - -
- )} - + )} + +
-
- + +
- + ); }; diff --git a/source/pages/Send/SendEth.tsx b/source/pages/Send/SendEth.tsx index 23baf888f..5057383ba 100644 --- a/source/pages/Send/SendEth.tsx +++ b/source/pages/Send/SendEth.tsx @@ -1,6 +1,7 @@ import { Menu, Transition } from '@headlessui/react'; import { ChevronDoubleDownIcon } from '@heroicons/react/solid'; -import { Form, Input } from 'antd'; +import { Form } from 'antd'; +import { toSvg } from 'jdenticon'; import { uniqueId } from 'lodash'; import React, { useEffect } from 'react'; import { useState, Fragment } from 'react'; @@ -9,12 +10,12 @@ import { useSelector } from 'react-redux'; import { isValidEthereumAddress } from '@pollum-io/sysweb3-utils'; -import { Card, Layout, NeutralButton } from 'components/index'; +import { Card, Layout, Button } from 'components/index'; import { useUtils } from 'hooks/index'; import { RootState } from 'state/store'; import { IERC1155Collection, ITokenEthProps } from 'types/tokens'; import { getController } from 'utils/browser'; -import { getAssetBalance } from 'utils/index'; +import { ellipsis, getAssetBalance } from 'utils/index'; export const SendEth = () => { const { alert, navigate } = useUtils(); @@ -34,9 +35,16 @@ export const SendEth = () => { gasPrice: 0, }); const [isMessageVisible, setIsMessageVisible] = useState(false); + const [inputValue, setInputValue] = useState({ address: '', amount: 0 }); + const [isValidAddress, setIsValidAddress] = useState(null); + const [isValidAmount, setIsValidAmount] = useState(null); + const [form] = Form.useForm(); const { wallet } = getController(); + const isAccountImported = + accounts[activeAccountMeta.type][activeAccountMeta.id]?.isImported; + const hasAccountAssets = activeAccount && activeAccount.assets.ethereum?.length > 0; @@ -45,6 +53,23 @@ export const SendEth = () => { const messageOpacity = isMessageVisible ? 'opacity-100' : 'opacity-0'; + const handleInputChange = (e) => { + const { name, value } = e.target; + + setInputValue((prevState) => ({ ...prevState, [name]: value })); + + if (name === 'address' && value.trim() !== '') { + const validAddress = isValidEthereumAddress(value); + setIsValidAddress(validAddress); + } else if (name === 'amount') { + const validAmount = + value <= Number(activeAccount?.balances.ethereum) && value > 0; + setIsValidAmount(validAmount); + } else { + setIsValidAddress(null); + } + }; + const handleSelectedAsset = (item: string) => { if (activeAccount.assets.ethereum?.length > 0) { const getAsset = activeAccount.assets.ethereum.find( @@ -158,17 +183,51 @@ export const SendEth = () => { } }, [isMessageVisible]); + useEffect(() => { + const placeholder = document.querySelector('.add-identicon'); + if (!placeholder) return; + + placeholder.innerHTML = toSvg( + accounts[activeAccountMeta.type][activeAccountMeta.id]?.xpub, + 50, + { + backColor: '#07152B', + padding: 1, + } + ); + }, [accounts[activeAccountMeta.type][activeAccountMeta.id]?.address]); + return (
-

- - {t('send.balance')} - - - {finalBalance()} -

- +
+
+
+ +
+

+ {accounts[activeAccountMeta.type][activeAccountMeta.id]?.label} +

+

+ {ellipsis( + accounts[activeAccountMeta.type][activeAccountMeta.id] + ?.address, + 4, + 4 + )} +

+
+ {isAccountImported && ( +
+ Imported +
+ )} +
+
+

Your balance:

+

{finalBalance()}

+
+
{ }), ]} > - +
+ + {isValidAddress !== null && ( + {isValidAddress + )} +
-
+
{hasAccountAssets ? ( {
{String(getLabel())} @@ -250,7 +324,7 @@ export const SendEth = () => { {hasAccountAssets ? (
- { - setIsMessageVisible(true); - form.setFieldValue( - 'amount', - selectedAsset - ? selectedAsset.balance - : totalMaxNativeTokenValue - ); - }} - > - Max -
{
- {t('buttons.next')} +
diff --git a/source/pages/Send/SendNTokenTransaction.tsx b/source/pages/Send/SendNTokenTransaction.tsx index 1794ef6c9..fe692273a 100644 --- a/source/pages/Send/SendNTokenTransaction.tsx +++ b/source/pages/Send/SendNTokenTransaction.tsx @@ -22,7 +22,7 @@ import { verifyNetworkEIP1559Compatibility, } from 'utils/index'; -import { EditPriorityModal } from './EditPriorityModal'; +import { EditPriorityModal } from './EditPriority'; export const SendNTokenTransaction = () => { const { @@ -422,6 +422,16 @@ export const SendNTokenTransaction = () => { onClose={() => setHaveError(false)} /> + + { }} /> - - {tx.from && fee ? (

diff --git a/source/pages/Send/SendSys.tsx b/source/pages/Send/SendSys.tsx index a94801bae..177892af1 100644 --- a/source/pages/Send/SendSys.tsx +++ b/source/pages/Send/SendSys.tsx @@ -1,6 +1,7 @@ import { Switch, Menu, Transition } from '@headlessui/react'; import { ChevronDoubleDownIcon } from '@heroicons/react/solid'; import { Form, Input } from 'antd'; +import { toSvg } from 'jdenticon'; import { uniqueId } from 'lodash'; import * as React from 'react'; import { useState, useEffect, Fragment, useCallback, useMemo } from 'react'; @@ -10,13 +11,19 @@ import { useSelector } from 'react-redux'; //todo: update with the new function import { isValidSYSAddress } from '@pollum-io/sysweb3-utils'; -import { Tooltip, Fee, NeutralButton, Layout } from 'components/index'; +import { Tooltip, Fee, NeutralButton, Layout, Icon } from 'components/index'; import { usePrice, useUtils } from 'hooks/index'; import { IPriceState } from 'state/price/types'; import { RootState } from 'state/store'; import { ITokenSysProps } from 'types/tokens'; import { getController } from 'utils/browser'; -import { truncate, isNFT, getAssetBalance, formatCurrency } from 'utils/index'; +import { + truncate, + isNFT, + getAssetBalance, + formatCurrency, + ellipsis, +} from 'utils/index'; export const SendSys = () => { const { getFiatAmount } = usePrice(); @@ -50,6 +57,9 @@ export const SendSys = () => { form.setFieldsValue({ fee: getRecommendedFee || Number(0.00001) }); }, [controller.wallet.account, form]); + const isAccountImported = + accounts[activeAccountMeta.type][activeAccountMeta.id]?.isImported; + useEffect(() => { handleGetFee(); @@ -150,20 +160,57 @@ export const SendSys = () => { return getAmount; }, [selectedAsset, recommendedFee]); + useEffect(() => { + const placeholder = document.querySelector('.add-identicon'); + if (!placeholder) return; + + placeholder.innerHTML = toSvg( + accounts[activeAccountMeta.type][activeAccountMeta.id]?.xpub, + 50, + { + backColor: '#07152B', + padding: 1, + } + ); + }, [accounts[activeAccountMeta.type][activeAccountMeta.id]?.address]); + return (

-

- - {t('send.balance')} - - - {selectedAsset - ? getAssetBalance(selectedAsset, activeAccount, true) - : `${activeAccount.balances.syscoin} ${activeNetwork.currency}`} -

+
+
+
+ +
+

+ {accounts[activeAccountMeta.type][activeAccountMeta.id]?.label} +

+

+ {ellipsis( + accounts[activeAccountMeta.type][activeAccountMeta.id] + ?.address, + 4, + 4 + )} +

+
+ {isAccountImported && ( +
+ Imported +
+ )} +
+
+

Your balance:

+

+ {selectedAsset + ? getAssetBalance(selectedAsset, activeAccount, true) + : `${activeAccount.balances.syscoin} ${activeNetwork.currency}`} +

+
+
{ }} onFinish={nextStep} autoComplete="off" - className="flex flex-col gap-2 items-center justify-center mt-1 text-center md:w-full" + className="flex flex-col gap-2 items-center justify-center mt-6 text-center md:w-full" > { +
+
+ { + + +
+ + {truncate( + String( + selectedAsset?.symbol + ? selectedAsset?.symbol + : activeNetwork.currency + ), + 4 + )} + + + + + + { + + + + + + {activeAccount.assets.syscoin.length > 0 + ? activeAccount.assets.syscoin.map( + (item: any) => ( + <> + {item?.assetGuid ? ( + + + + + + ) : null} + + ) + ) + : null} + + } + +
+
+
+ } +
-
- { +
- -
- - {truncate( - String( - selectedAsset?.symbol - ? selectedAsset?.symbol - : activeNetwork.currency - ), - 4 - )} - - - - - { - - - - - - {activeAccount.assets.syscoin.length > 0 - ? activeAccount.assets.syscoin.map((item: any) => ( - <> - {item?.assetGuid ? ( - - - - - - ) : null} - - )) - : null} - + () => ({ + validator(_, value) { + if (value <= balance) { + return Promise.resolve(); } - -
-
-
- } - -
- - -

- {t('send.verifyAddress')} -

-
- - - {t('send.verifyAddress')} - - -
- - -

- Z-DAG -

-
- - Z-DAG +
+ form.setFieldValue( + 'amount', + balance - 1.01 * recommendedFee + ) + } + > + MAX + + - +
- -
+ + +
+
+ + {t('send.verifyAddress')} + + + + +
({ - validator(_, value) { - if (value <= balance) { - return Promise.resolve(); - } - - return Promise.reject(); - }, - }), ]} > - + + + - - form.setFieldValue('amount', balance - 1.01 * recommendedFee) - } +
+
+
+ Z-DAG + + + +
+ - Max - + + + +
- - -

- - {`${t('transactions.withCurrentNetwork')} ${recommendedFee} SYS`} - - - - {'≈ '} - {fiatValueToShow} - -

- -
- +
+ {t('buttons.next')}
diff --git a/source/pages/Send/SendTransaction.tsx b/source/pages/Send/SendTransaction.tsx index ae4fd60a8..195ba4a1c 100644 --- a/source/pages/Send/SendTransaction.tsx +++ b/source/pages/Send/SendTransaction.tsx @@ -27,7 +27,7 @@ import { TransactionDataComponent, TransactionHexComponent, } from './components'; -import { EditPriorityModal } from './EditPriorityModal'; +import { EditPriorityModal } from './EditPriority'; import { tabComponents, tabElements } from './mockedComponentsData/mockedTabs'; export const SendTransaction = () => { @@ -252,6 +252,15 @@ export const SendTransaction = () => { }} /> + + { }} /> - - {tx?.from ? (
diff --git a/source/pages/Send/components/PriorityBar.tsx b/source/pages/Send/components/PriorityBar.tsx index 67ee8afc7..d4a138eb8 100644 --- a/source/pages/Send/components/PriorityBar.tsx +++ b/source/pages/Send/components/PriorityBar.tsx @@ -1,8 +1,8 @@ import React, { Dispatch, SetStateAction } from 'react'; import { useTranslation } from 'react-i18next'; -export const PinkBall = () => ( -
+export const WhiteBall = () => ( +
); export const Ball = ({ @@ -13,15 +13,15 @@ export const Ball = ({ selected?: boolean; }) => (
-
- {selected && } +
+ {selected && }
-
+

{label} @@ -44,7 +44,7 @@ export const PriorityBar = ({ }; return ( -

+
{Object.entries(values).map(([key, value]) => (
onClick(Number(key))}> diff --git a/source/pages/Send/index.tsx b/source/pages/Send/index.tsx index ad33a989c..0b0161971 100755 --- a/source/pages/Send/index.tsx +++ b/source/pages/Send/index.tsx @@ -4,5 +4,5 @@ export { SendEth } from './SendEth'; export { SendSys } from './SendSys'; export { EditApprovedAllowanceValueModal } from './EditApprovedAllowanceValueModal'; export { ApproveTransactionComponent } from './Approve'; -export { EditPriorityModal } from './EditPriorityModal'; +export { EditPriorityModal } from './EditPriority'; export { SendNTokenTransaction } from './SendNTokenTransaction'; diff --git a/source/pages/Tokens/CustomToken.tsx b/source/pages/Tokens/CustomToken.tsx index 3c4d184ab..3e75addeb 100644 --- a/source/pages/Tokens/CustomToken.tsx +++ b/source/pages/Tokens/CustomToken.tsx @@ -471,7 +471,7 @@ export const CustomToken = (props: ICustomTokenComponentProps) => { readOnly={isEdit} type="text" disabled={isEdit} - className="input-small relative" + className="custom-import-input relative" placeholder={t('tokens.contractAddress')} /> @@ -519,7 +519,7 @@ export const CustomToken = (props: ICustomTokenComponentProps) => { > @@ -574,7 +574,7 @@ export const CustomToken = (props: ICustomTokenComponentProps) => { > { path="send/confirm" element={} />} /> - } />} - /> } />