From 027fb789601fe22a4c2dc09b04e47809bfe1e85f Mon Sep 17 00:00:00 2001 From: Lautaro Petaccio <1120791+LautaroPetaccio@users.noreply.github.com> Date: Tue, 18 Feb 2025 15:47:44 -0300 Subject: [PATCH] feat: Add Web2 transaction modal (#569) * feat: Add Web2 transaction modal * fix: Compute the difference between the transaction cost and user balance manually --- .../Web2TransactionModal.css | 52 ++++++++ .../Web2TransactionModal.stories.tsx | 24 ++++ .../Web2TransactionModal.tsx | 119 ++++++++++++++++++ src/components/Web2TransactionModal/index.ts | 1 + src/index.ts | 1 + 5 files changed, 197 insertions(+) create mode 100644 src/components/Web2TransactionModal/Web2TransactionModal.css create mode 100644 src/components/Web2TransactionModal/Web2TransactionModal.stories.tsx create mode 100644 src/components/Web2TransactionModal/Web2TransactionModal.tsx create mode 100644 src/components/Web2TransactionModal/index.ts diff --git a/src/components/Web2TransactionModal/Web2TransactionModal.css b/src/components/Web2TransactionModal/Web2TransactionModal.css new file mode 100644 index 00000000..ecf94572 --- /dev/null +++ b/src/components/Web2TransactionModal/Web2TransactionModal.css @@ -0,0 +1,52 @@ +.dcl.web2-transaction-modal-content > p { + padding: 0; + margin: 0; +} + +.dcl.web2-transaction-modal-content { + display: flex; + flex-direction: column; + gap: 16px; + padding: 10px; +} + +.dcl.web2-transaction-modal-content-transaction-cost { + display: flex; + flex-direction: column; + gap: 16px; + background-color: #67637033; + padding: 16px; + border-radius: 8px; +} + +.dcl.web2-transaction-modal-content-transaction-cost-row { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; +} + +@media (max-width: 768px) { + .dcl.web2-transaction-modal-content-container { + display: flex; + flex-grow: 1; + } + + .dcl.web2-transaction-modal-content { + padding: 0; + } + + .ui.modal > .dcl.web2-transaction-modal-actions.actions .button { + margin: 0; + } + + .ui.modal > .dcl.web2-transaction-modal-actions.actions { + display: flex; + flex-direction: column-reverse; + gap: 15px; + } + + .dcl.web2-transaction-modal-content-transaction-cost-row { + flex-direction: column; + } +} diff --git a/src/components/Web2TransactionModal/Web2TransactionModal.stories.tsx b/src/components/Web2TransactionModal/Web2TransactionModal.stories.tsx new file mode 100644 index 00000000..a51f0317 --- /dev/null +++ b/src/components/Web2TransactionModal/Web2TransactionModal.stories.tsx @@ -0,0 +1,24 @@ +import React from 'react' +import { ComponentMeta, ComponentStory } from '@storybook/react' +import { Web2TransactionModal } from './Web2TransactionModal' +import { ChainId } from '@dcl/schemas' + +export default { + title: 'Web2TransactionModal', + component: Web2TransactionModal +} as ComponentMeta + +const Template: ComponentStory = (args) => ( + +) + +export const Basic = Template.bind({}) +Basic.args = { + transactionCostAmount: '0.005', + userBalanceAmount: '1', + chainId: ChainId.ETHEREUM_MAINNET, + isOpen: true, + onAccept: () => console.log('accept'), + onClose: () => console.log('close'), + onReject: () => console.log('reject') +} diff --git a/src/components/Web2TransactionModal/Web2TransactionModal.tsx b/src/components/Web2TransactionModal/Web2TransactionModal.tsx new file mode 100644 index 00000000..c00d25dd --- /dev/null +++ b/src/components/Web2TransactionModal/Web2TransactionModal.tsx @@ -0,0 +1,119 @@ +import React from 'react' +import { ChainId, getChainName, Network } from '@dcl/schemas' +import { Button } from '../Button/Button' +import { Modal } from '../Modal/Modal' +import { ModalNavigation } from '../ModalNavigation/ModalNavigation' +import { Message } from '../Message/Message' +import './Web2TransactionModal.css' +import { getNetwork } from '@dcl/schemas/dist/dapps/chain-id' + +export type Web2TransactionModalProps = { + /* The transaction cost in ether */ + transactionCostAmount: string | number + /* The user balance in ether */ + userBalanceAmount: string | number + chainId: ChainId + isOpen?: boolean + onAccept: () => void + onClose: () => void + onReject: () => void + i18n?: { + title?: React.ReactNode + description?: (networkName: React.ReactNode) => string + gasExplanation?: React.ReactNode + transactionCostTitle?: React.ReactNode + userBalanceTitle?: React.ReactNode + balanceNotEnoughTitle?: React.ReactNode + balanceNotEnoughContent?: React.ReactNode + accept?: React.ReactNode + reject?: React.ReactNode + } +} + +export const Web2TransactionModal = (props: Web2TransactionModalProps) => { + const { + chainId, + onAccept, + onClose, + onReject, + i18n, + isOpen, + transactionCostAmount, + userBalanceAmount + } = props + + // Build the internationalized strings + const title = i18n?.title || 'Confirm Transaction' + const description = + i18n?.description || + ((networkName) => ( + <> + You are about to perform a transaction on the {networkName}{' '} + network. + + )) + const gasExplanation = i18n?.gasExplanation || ( + <> + Network transactions require gas, paid in the network's native currency. + For more information about gas, click{' '} + + here + + . + + ) + const balanceNotEnoughTitle = + i18n?.balanceNotEnoughTitle ?? 'Insufficient Balance' + const balanceNotEnoughContent = + i18n?.balanceNotEnoughContent ?? + 'Your balance may be insufficient to cover this transaction. If the transaction cannot be completed, please add more of the necessary currency to your account and try again.' + const transactionCostTitle = + i18n?.transactionCostTitle ?? 'Estimated Gas Fee:' + const userBalanceTitle = i18n?.userBalanceTitle ?? 'Your Balance:' + const accept = i18n?.accept ?? 'Continue' + const reject = i18n?.reject ?? 'Cancel' + + const networkName = getChainName(chainId) + return ( + + + +
+

{description(networkName)}

+

{gasExplanation}

+
+
+
{transactionCostTitle}
+
+ {transactionCostAmount}{' '} + {getNetwork(chainId) === Network.ETHEREUM ? 'ETH' : 'MATIC'} +
+
+
+
{userBalanceTitle}
+
+ {userBalanceAmount}{' '} + {getNetwork(chainId) === Network.ETHEREUM ? 'ETH' : 'MATIC'} +
+
+
+ {Number(transactionCostAmount) > Number(userBalanceAmount) && ( + + )} +
+
+ + + + +
+ ) +} diff --git a/src/components/Web2TransactionModal/index.ts b/src/components/Web2TransactionModal/index.ts new file mode 100644 index 00000000..1d197d6d --- /dev/null +++ b/src/components/Web2TransactionModal/index.ts @@ -0,0 +1 @@ +export * from './Web2TransactionModal' diff --git a/src/index.ts b/src/index.ts index e2468d60..aa25b081 100644 --- a/src/index.ts +++ b/src/index.ts @@ -101,6 +101,7 @@ export * from './components/CommunityBubble' export * from './components/AddressField' export * from './components/Loader/LoadingText' export * from './components/RarityBadge' +export * from './components/Web2TransactionModal' // Semantic components /* eslint-disable no-restricted-imports */ export * from 'semantic-ui-react'