Skip to content

Commit 756ba0b

Browse files
authored
Merge pull request #55 from tari-project/feat/display-new-statuses
feat: display new statuses
2 parents c187b61 + 65697a8 commit 756ba0b

File tree

20 files changed

+299
-130
lines changed

20 files changed

+299
-130
lines changed

app/page.tsx

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ import { Network } from '@/components/network-box'
1313
import useTariAccount from '@/store/account'
1414
import { useBridgeToEthereumFees } from '@/hooks/use-bridge-to-ethereum-fees'
1515
import { useBridgeTransaction } from '@/hooks/use-bridge-transaction'
16+
import { UserTransactionDTO } from '@tari-project/wxtm-bridge-backend-api'
1617

1718
export default function Home() {
1819
const { isConnected, address: ethAddress } = useAccount()
1920
const [modalOpen, setModalOpen] = useState(false)
2021
const [modalStep, setModalStep] = useState<number>(1)
21-
const [success] = useState(false)
2222
const [fromNetwork, setFromNetwork] = useState<Network>({
2323
name: 'Tari',
2424
icon: '/icons/tari.png',
@@ -28,10 +28,8 @@ export default function Home() {
2828
icon: '/icons/eth.png',
2929
})
3030

31-
const { bridgeToEthereum, isBridging, getBridgeTxParams } =
32-
useBridgeToEthereum()
33-
const { tariAccount, isProcessingTransaction, pendingBridgeTx } =
34-
useTariAccount()
31+
const { bridgeToEthereum, getBridgeTxParams } = useBridgeToEthereum()
32+
const { tariAccount, isOngoingBridgeTx, ongoingBridgeTx } = useTariAccount()
3533
const { getUserTransactions } = useBridgeTransaction()
3634

3735
const {
@@ -47,35 +45,58 @@ export default function Home() {
4745
const amount = watch('amount')
4846
const feesData = useBridgeToEthereumFees(amount)
4947

48+
// Fetch bridge transaction parameters once on mount or when tariAccount changes
5049
useEffect(() => {
51-
if (tariAccount) {
52-
const fetchUserTransactions = async () => {
53-
try {
54-
await getUserTransactions(tariAccount.address, pendingBridgeTx)
55-
await getBridgeTxParams()
56-
} catch (error) {
57-
console.error(
58-
'[ TAPPLET-BRIDGE ] Failed to get user transactions:',
59-
error,
60-
)
61-
}
50+
if (!tariAccount) return
51+
52+
const fetchBridgeTxParams = async () => {
53+
try {
54+
await getBridgeTxParams()
55+
} catch (error) {
56+
console.error(
57+
'[ TAPPLET-BRIDGE ] Failed to get bridge transaction params:',
58+
error,
59+
)
6260
}
61+
}
62+
63+
fetchBridgeTxParams()
64+
// eslint-disable-next-line react-hooks/exhaustive-deps
65+
}, [tariAccount])
66+
67+
useEffect(() => {
68+
if (!tariAccount) return
69+
70+
const fetchUserTransactions = async () => {
71+
try {
72+
await getUserTransactions()
73+
} catch (error) {
74+
console.error(
75+
'[ TAPPLET-BRIDGE ] Failed to get user transactions:',
76+
error,
77+
)
78+
}
79+
}
80+
81+
fetchUserTransactions()
82+
// Poll every 1 min
83+
const intervalId = setInterval(fetchUserTransactions, 60000)
6384

64-
fetchUserTransactions()
85+
return () => {
86+
clearInterval(intervalId)
6587
}
6688
// eslint-disable-next-line react-hooks/exhaustive-deps
6789
}, [tariAccount])
6890

69-
// Auto-close modal when connected and on connect step
7091
useEffect(() => {
7192
if (modalOpen && modalStep === 0 && isConnected) {
7293
setModalOpen(false)
7394
setModalStep(1)
74-
} else if (isProcessingTransaction) {
95+
} else if (isOngoingBridgeTx && ongoingBridgeTx) {
7596
setModalStep(2)
7697
setModalOpen(true)
7798
}
78-
}, [isConnected, modalOpen, modalStep, isProcessingTransaction])
99+
}, [isConnected, modalOpen, modalStep, isOngoingBridgeTx, ongoingBridgeTx])
79100

80101
const handleConnectClick = () => {
81102
if (!isConnected) {
@@ -96,16 +117,15 @@ export default function Home() {
96117

97118
bridgeToEthereum({
98119
amount,
99-
amountAfterFee: feesData.amountAfterFee,
100120
ethAddress: ethAddress,
101121
})
102122
.then(() => {
103-
setModalStep(2)
123+
getUserTransactions()
104124
})
105125
.catch((error) => {
106126
console.error('[ TAPPLET-BRIDGE ] Bridge operation failed:', error)
107127
})
108-
}, [amount, ethAddress, bridgeToEthereum, feesData])
128+
}, [amount, ethAddress, bridgeToEthereum, getUserTransactions])
109129

110130
const handleBridgeToTari = () => {
111131
setModalStep(2)
@@ -125,17 +145,20 @@ export default function Home() {
125145
setFromNetwork={setFromNetwork}
126146
toNetwork={toNetwork}
127147
setToNetwork={setToNetwork}
128-
isProcessingTransaction={isProcessingTransaction || isBridging}
148+
isOngoingBridgeTx={isOngoingBridgeTx}
129149
/>
130150
{modalOpen && (
131151
<MainModal
132152
setModalOpen={setModalOpen}
133-
success={success}
153+
success={
154+
ongoingBridgeTx?.status === UserTransactionDTO.status.SUCCESS
155+
}
156+
failed={ongoingBridgeTx?.status === UserTransactionDTO.status.TIMEOUT}
134157
step={modalStep}
135158
setStep={setModalStep}
136159
handleBridgeToEthereum={handleBridgeToEthereum}
137160
handleBridgeToTari={handleBridgeToTari}
138-
isBridging={isBridging}
161+
isBridging={isOngoingBridgeTx}
139162
amount={amount}
140163
ethereumAddress={ethAddress}
141164
tariWalletAddress={tariAccount?.address}

components/main/main.component.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const MainComponent: React.FC<MainComponentProps> = ({
3131
setFromNetwork,
3232
toNetwork,
3333
setToNetwork,
34-
isProcessingTransaction,
34+
isOngoingBridgeTx,
3535
}) => {
3636
const [openDropdown, setOpenDropdown] = useState<'from' | 'to' | null>(null)
3737

@@ -50,7 +50,7 @@ export const MainComponent: React.FC<MainComponentProps> = ({
5050
const evm_balance = data?.value
5151
? parseFloat(ethers.formatEther(data?.value)).toPrecision(4)
5252
: '0'
53-
const isDisabled = chain === undefined || isProcessingTransaction
53+
const isDisabled = chain === undefined || isOngoingBridgeTx
5454

5555
const fromNetworks = networks.filter(
5656
(n) => n.name === 'Ethereum' || n.name === 'Tari',

components/main/main.types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@ export type MainComponentProps = {
1111
setFromNetwork: React.Dispatch<React.SetStateAction<Network>>
1212
toNetwork: Network
1313
setToNetwork: React.Dispatch<React.SetStateAction<Network>>
14-
isProcessingTransaction: boolean
14+
isOngoingBridgeTx: boolean
1515
} & Pick<BridgeInputProps, 'control' | 'errors'>
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import React, { useCallback } from 'react'
2+
import Image from 'next/image'
3+
import { FailedModalProps } from './failed-modal.types'
4+
import { ModalButton } from '@/components/modals/modal-button'
5+
6+
import useTariAccount from '@/store/account'
7+
8+
export const FailedModal: React.FC<FailedModalProps> = ({ closeModal }) => {
9+
const { removeOngoingTransaction, ongoingBridgeTx } = useTariAccount()
10+
11+
const handleOnClick = useCallback(() => {
12+
closeModal()
13+
removeOngoingTransaction()
14+
}, [closeModal, removeOngoingTransaction])
15+
16+
return (
17+
<div className="w-full flex flex-col p-6">
18+
<div className="mt-2">
19+
{/* Top Section */}
20+
<div className="flex flex-col items-center justify-center">
21+
<div className="w-[49px] h-[49px] rounded-full overflow-hidden mr-1 relative">
22+
<Image
23+
src="/icons/timeout.png"
24+
fill
25+
sizes="49px"
26+
alt="Timeout"
27+
className="rounded-full object-cover"
28+
/>
29+
</div>
30+
<div className="font-semibold text-lg mt-2">Something went wrong</div>
31+
<div className="font-normal text-xs mt-2 text-center px-3">
32+
We couldn&apos;t complete your wrapping request in time. <br /> Your
33+
XTM remains safe in your Tari wallet — it hasn&apos;t been deducted
34+
or moved.
35+
</div>
36+
</div>
37+
38+
{/* Section 1 */}
39+
<div className="flex flex-col my-4">
40+
<div className="font-medium">
41+
<div className="text-xs text-gray-500">Transaction ID</div>
42+
<div className="text-sm">{ongoingBridgeTx?.paymentId}</div>
43+
</div>
44+
45+
<div className="py-[0.5px] w-full bg-gray-300 my-2"></div>
46+
<ModalButton label="Retry" onClick={handleOnClick} disabled={false} />
47+
</div>
48+
</div>
49+
</div>
50+
)
51+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type FailedModalProps = {
2+
closeModal: () => void
3+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './failed-modal'
2+
export * from './failed-modal.types'

components/modals/main-modal/main-modal.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ import { ReviewModal } from '@/components/modals/review-modal'
88
import { SuccessModal } from '@/components/modals/success-modal'
99
import { WrapModal } from '@/components/modals/wrap-modal'
1010
import { MainModalProps } from './main-modal.types'
11+
import { FailedModal } from '../failed-modal'
1112

1213
export const MainModal: React.FC<MainModalProps> = ({
1314
setModalOpen,
1415
success,
16+
failed,
1517
step,
1618
setStep,
1719
handleBridgeToEthereum,
@@ -26,7 +28,6 @@ export const MainModal: React.FC<MainModalProps> = ({
2628
}) => {
2729
const { isConnected } = useAccount()
2830
const modalRef = useRef<HTMLDivElement>(null)
29-
// const feesData = useBridgeToEthereumFees(amount)
3031

3132
const closeModal = () => {
3233
setModalOpen(false)
@@ -50,10 +51,11 @@ export const MainModal: React.FC<MainModalProps> = ({
5051
tariWalletAddress={tariWalletAddress}
5152
ethereumAddress={ethereumAddress}
5253
fromNetwork={fromNetwork}
53-
feesData={feesData}
5454
/>
5555
)
5656

57+
if (failed) return <FailedModal closeModal={closeModal} />
58+
5759
if (!isConnected && step === 0)
5860
return <ConnectionModal closeModal={closeModal} />
5961
if (step === 1)
@@ -75,7 +77,6 @@ export const MainModal: React.FC<MainModalProps> = ({
7577
return (
7678
<WrapModal
7779
closeModal={closeModal}
78-
amount={amount}
7980
tariWalletAddress={tariWalletAddress}
8081
ethereumAddress={ethereumAddress}
8182
fromNetwork={fromNetwork}

components/modals/main-modal/main-modal.types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { BridgeToEthereumFees } from '@/hooks/use-bridge-to-ethereum-fees'
44
export type MainModalProps = {
55
setModalOpen: (open: boolean) => void
66
success: boolean
7+
failed: boolean
78
step: number
89
setStep: (step: number) => void
910
handleBridgeToEthereum: () => void

components/modals/success-modal/success-modal.tsx

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,39 @@
1-
import React from 'react'
1+
import React, { useCallback } from 'react'
22
import Image from 'next/image'
3-
import { HiArrowRightOnRectangle } from 'react-icons/hi2'
3+
// import { HiArrowRightOnRectangle } from 'react-icons/hi2'
44
import { SuccessModalProps } from './success-modal.types'
55
import { ModalButton } from '@/components/modals/modal-button'
66
import { useBridgeInfo } from '@/hooks/use-bridge-info'
7+
import useTariAccount from '@/store/account'
8+
import { formatUnits } from 'ethers'
79

810
export const SuccessModal: React.FC<SuccessModalProps> = ({
911
closeModal,
10-
amount,
1112
tariWalletAddress,
1213
ethereumAddress,
1314
fromNetwork,
14-
feesData: { amountAfterFee },
1515
}) => {
16-
/** @dev Tmp hardcoded tx hash */
17-
const txhash =
18-
'0x0bec7941a37c07ec7cd408b3478c66ac7a26c4e48c2fd22577bb2c9c44cb4ae8'
16+
const { removeOngoingTransaction, ongoingBridgeTx } = useTariAccount()
1917

20-
const { fromToken, toToken, destAddress } = useBridgeInfo(
18+
const { fromToken, toToken } = useBridgeInfo(
2119
fromNetwork,
2220
ethereumAddress!,
2321
tariWalletAddress!,
2422
)
2523

24+
const handleOnClick = useCallback(() => {
25+
closeModal()
26+
removeOngoingTransaction()
27+
}, [closeModal, removeOngoingTransaction])
28+
29+
const amount = ongoingBridgeTx?.tokenAmount
30+
? parseFloat(formatUnits(ongoingBridgeTx?.tokenAmount, 6)).toPrecision()
31+
: '0'
32+
33+
const amountToReceive = ongoingBridgeTx?.amountAfterFee
34+
? parseFloat(formatUnits(ongoingBridgeTx?.amountAfterFee, 6)).toPrecision()
35+
: '0'
36+
2637
return (
2738
<div className="w-full flex flex-col p-6">
2839
<div className="mt-2">
@@ -39,7 +50,7 @@ export const SuccessModal: React.FC<SuccessModalProps> = ({
3950
</div>
4051
<div className="font-semibold text-lg mt-2">
4152
We&apos;ve {fromToken === 'wXTM' ? 'unwrapped' : 'wrapped'} your{' '}
42-
{parseFloat(amount).toPrecision()} {fromToken}!
53+
{amount} {fromToken}!
4354
</div>
4455
<div className="font-normal text-xs mt-2 text-center px-3">
4556
Your {toToken} conversion has been complete and your funds have been
@@ -52,20 +63,20 @@ export const SuccessModal: React.FC<SuccessModalProps> = ({
5263
<div className="font-medium">
5364
<div className="text-xs text-gray-500">Amount to receive</div>
5465
<div className="text-sm">
55-
{parseFloat(amountAfterFee).toPrecision()} {toToken}
66+
{amountToReceive} {toToken}
5667
</div>
5768
</div>
5869

5970
<div className="py-[0.5px] w-full bg-gray-300 my-2"></div>
6071

6172
<div className="font-medium">
6273
<div className="text-xs text-gray-500">Destination address</div>
63-
<div className="text-sm">{destAddress}</div>
74+
<div className="text-sm">{ongoingBridgeTx?.destinationAddress}</div>
6475
</div>
6576

6677
<div className="py-[0.5px] w-full bg-gray-300 my-2"></div>
6778

68-
<div className="font-medium">
79+
{/* <div className="font-medium">
6980
<div className="text-xs text-gray-500">Transaction Details</div>
7081
<a
7182
href="https://sepolia.etherscan.io/tx/0x0bec7941a37c07ec7cd408b3478c66ac7a26c4e48c2fd22577bb2c9c44cb4ae8"
@@ -78,7 +89,7 @@ export const SuccessModal: React.FC<SuccessModalProps> = ({
7889
</a>
7990
</div>
8091
81-
<div className="py-[0.5px] w-full bg-gray-300 my-2"></div>
92+
<div className="py-[0.5px] w-full bg-gray-300 my-2"></div> */}
8293

8394
{/* <div className="font-medium">
8495
<div className="text-xs text-gray-500">Transaction ID</div>
@@ -88,7 +99,7 @@ export const SuccessModal: React.FC<SuccessModalProps> = ({
8899
<div className="py-[0.5px] w-full bg-gray-300 mt-2 mb-4"></div> */}
89100

90101
{/* Section 1 */}
91-
<ModalButton label="Close" onClick={closeModal} disabled={false} />
102+
<ModalButton label="Close" onClick={handleOnClick} disabled={false} />
92103
</div>
93104
</div>
94105
</div>

components/modals/success-modal/success-modal.types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
import { MainModalProps } from '@/components/modals/main-modal'
2-
import { BridgeToEthereumFees } from '@/hooks/use-bridge-to-ethereum-fees'
32

43
export type SuccessModalProps = {
54
closeModal: () => void
6-
feesData: BridgeToEthereumFees
75
} & Pick<
86
MainModalProps,
97
'amount' | 'tariWalletAddress' | 'ethereumAddress' | 'fromNetwork'

0 commit comments

Comments
 (0)