Skip to content

Commit 911cf36

Browse files
authored
chore: bump deps and stores cleanups (#100)
Description --- - bumped dependencies not on `wanted` version - adjusted code for upgrades where needed - cleaned up store actions (move out of stores to prevent re-renders) - added a disconnect option for your wallet - cleaned up unused items - cleaned up prop drilling (added a modal store, used `FormProvider`) Motivation and Context --- - hopefully fixes the WalletConnect copy url issue on windows :) - general cleanup How Has This Been Tested? --- - locally (not connected to TU) - locally, built and used within TU **wrapping + error messaging (fees for unwrap were super high):** https://github.com/user-attachments/assets/5bfdcebc-a1bd-450a-98f6-a185113eb0da **unwrappin:** https://github.com/user-attachments/assets/d3e1c5cf-285f-47b3-8304-9c4902978ee8 Breaking Changes --- - [x] None
1 parent e41aaa3 commit 911cf36

58 files changed

Lines changed: 5065 additions & 5803 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.npmrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Use for: 'wxtm-bridge-backend-api' update
2-
@tari-project:registry=https://registry.npmjs.org/
2+
# @tari-project:registry=https://registry.npmjs.org/
33

44
# Use for: 'wxtm-bridge-contracts' update
5-
@tari-project:registry=https://npm.pkg.github.com/
5+
# @tari-project:registry=https://npm.pkg.github.com/

app/favicon.ico

-15.8 KB
Binary file not shown.

app/page.tsx

Lines changed: 83 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -1,278 +1,156 @@
11
'use client'
2-
import React, { useCallback, useEffect, useState } from 'react'
3-
import { useForm } from 'react-hook-form'
4-
import { useAccount } from 'wagmi'
2+
import React, { useCallback, useEffect, useEffectEvent, useState } from 'react'
3+
import { FormProvider, useForm, useWatch } from 'react-hook-form'
4+
import { useConnection } from 'wagmi'
55
import './i18initializer'
66

77
import { BridgeFormValues } from '@/components/bridge-input'
88
import { Header } from '@/components/header'
99
import { MainComponent } from '@/components/main'
1010
import { MainModal } from '@/components/modals/main-modal'
1111
import { TransactionDetailsModal } from '@/components/modals/transaction-details-modal'
12-
import { Network } from '@/components/network-box'
1312
import { useBridgeFees } from '@/hooks/use-bridge-fees'
1413
import { useBridgeToEthereum } from '@/hooks/use-bridge-to-ethereum'
15-
import { useBridgeToTari } from '@/hooks/use-bridge-to-tari'
14+
1615
import { useBridgeTransaction } from '@/hooks/use-bridge-transaction'
17-
import useTariAccountStore from '@/store/account'
18-
import { TokensUnwrappedService, UserTransactionDTO } from '@tari-project/wxtm-bridge-backend-api'
19-
import { DeployedChains } from '@tari-project/wxtm-bridge-contracts/deployments'
16+
import { setDetailedTx, setLastOngoingBridgeTx, useTariAccountStore } from '@/store/account'
17+
import { UserTransactionDTO } from '@tari-project/wxtm-bridge-backend-api'
2018
import { FooterText } from '@/components/main/footer-text'
21-
import useBridgeStore from '@/store/bridge'
22-
import { microXtmToXtm } from '@/utils/parse-wxtm-token-amount'
19+
import { setUnwrapFailed, useBridgeStore } from '@/store/bridge'
20+
import { useFetchDailyLimit } from '@/hooks/use-fetch-daily-limit'
21+
import { setIsModalOpen, setModalStep, useModalStore } from '@/store/modal'
2322

24-
const DAILY_LIMIT_ERROR = 'Daily wrap limit exceeded'
25-
const DAILY_LIMIT_ERROR_TYPE = 'Forbidden'
26-
const REFETCH_LIMIT_INTERVAL = 30000
23+
const REFETCH_LIMIT_INTERVAL = 30 * 1000 // 30 sec
2724

2825
export default function Home() {
29-
const { isConnected, chain, address: ethAddress } = useAccount()
30-
const [hasFetchedParams, setHasFetchedParams] = useState(false)
31-
const [modalOpen, setModalOpen] = useState(false)
32-
const [modalStep, setModalStep] = useState<number>(1)
33-
const [fromNetwork, setFromNetwork] = useState<Network>({
34-
name: 'Tari',
35-
icon: '/icons/tari.png',
36-
})
37-
const [toNetwork, setToNetwork] = useState<Network>({
38-
name: 'Ethereum',
39-
icon: '/icons/eth.png',
40-
})
41-
const [isUnwrapping, setIsUnwrapping] = useState(false)
42-
const [isUnwrappingFailed, setIsUnwrappingFailed] = useState(false)
43-
const [remainingDailyLimit, setRemainingDailyLimit] = useState<number | undefined>(undefined)
44-
45-
const chainId = (chain?.id ?? 1) as DeployedChains
46-
47-
const { bridgeToEthereum, getBridgeTxParams } = useBridgeToEthereum()
48-
const { bridgeToTari, isPending, isSuccess, isError, error } = useBridgeToTari(ethAddress || '0x', chainId)
49-
const { getUserBackendBridgeTxs } = useBridgeTransaction()
50-
const tariAccount = useTariAccountStore((s) => s.tariAccount)
51-
const setExceededDailyLimit = useTariAccountStore((s) => s.setExceededDailyLimit)
52-
const setTariAccount = useTariAccountStore((s) => s.setTariAccount)
26+
const modalStep = useModalStore((s) => s.modalStep)
27+
const isModalOpen = useModalStore((s) => s.isModalOpen)
5328
const detailedTx = useTariAccountStore((s) => s.detailedTx)
54-
const setDetailedTx = useTariAccountStore((s) => s.setDetailedTx)
29+
const tariAccount = useTariAccountStore((s) => s.tariAccount)
5530
const ongoingBridgeTx = useTariAccountStore((s) => s.ongoingBridgeTx)
56-
const setLastOngoingBridgeTx = useTariAccountStore((s) => s.setLastOngoingBridgeTx)
5731
const tariColdWalletAddress = useBridgeStore((s) => s.tariColdWalletAddress)
5832
const wrapTokenFeePercentageBps = useBridgeStore((s) => s.wrapTokenFeePercentageBps)
33+
const fromNetwork = useBridgeStore((s) => s.fromNetwork)
34+
const isUnwrappingFailed = useBridgeStore((s) => s.unwrapFailed)
35+
const unwrapSuccess = useBridgeStore((s) => s.unwrapSuccess)
36+
37+
const fetchDailyLimit = useFetchDailyLimit()
38+
const { isConnected, address: ethAddress } = useConnection()
39+
const { getUserBackendBridgeTxs } = useBridgeTransaction()
40+
const { getBridgeTxParams } = useBridgeToEthereum()
41+
const methods = useForm<BridgeFormValues>({
42+
defaultValues: { amount: '' },
43+
mode: 'onChange',
44+
})
45+
const { control, resetField } = methods
46+
const amount = useWatch({ control, name: 'amount' })
47+
48+
const [hasFetchedParams, setHasFetchedParams] = useState(false)
49+
const [remainingDailyLimit, setRemainingDailyLimit] = useState<number | undefined>(undefined)
5950

6051
// Prevent main modal from showing when transaction details modal is active
6152
const showModalDetailedTx = !!detailedTx
6253
const showModalOngoingTx = ongoingBridgeTx && ongoingBridgeTx.showModal
63-
6454
const isFailed = ongoingBridgeTx?.status === UserTransactionDTO.status.TIMEOUT || isUnwrappingFailed
6555
const isWrapSuccess = ongoingBridgeTx?.status === UserTransactionDTO.status.SUCCESS
6656

67-
const {
68-
watch,
69-
control,
70-
setValue,
71-
formState: { errors, isValid },
72-
resetField,
73-
} = useForm<BridgeFormValues>({
74-
defaultValues: { amount: '' },
75-
mode: 'onChange',
76-
})
77-
78-
const amount = watch('amount')
7957
const decimals = fromNetwork.name === 'Tari' ? 6 : 18
8058
const feesData = useBridgeFees(amount, decimals)
8159

60+
const fetchUserTransactions = useCallback(async () => {
61+
if (tariAccount) {
62+
try {
63+
await getUserBackendBridgeTxs()
64+
} catch (error) {
65+
console.error('[ TAPPLET-BRIDGE ] Failed to get user transactions:', error)
66+
}
67+
}
68+
}, [getUserBackendBridgeTxs, tariAccount])
69+
70+
const onNetworkChange = useEffectEvent(() => setRemainingDailyLimit(undefined))
71+
const onFetchedParams = useEffectEvent((hasFetched: boolean) => setHasFetchedParams(hasFetched))
72+
8273
useEffect(() => {
8374
if (!tariAccount || hasFetchedParams) return
8475
const fetchBridgeTxParams = async () => {
8576
try {
8677
await getBridgeTxParams()
78+
setHasFetchedParams(true)
8779
} catch (error) {
8880
console.error('[ TAPPLET-BRIDGE ] Failed to get bridge transaction params:', error)
8981
}
9082
}
9183

92-
fetchBridgeTxParams().then(() => {
93-
setHasFetchedParams(true)
94-
})
95-
}, [getBridgeTxParams, hasFetchedParams, tariAccount])
84+
fetchBridgeTxParams().then(
85+
async () => await fetchUserTransactions(), //initial
86+
)
87+
}, [fetchUserTransactions, getBridgeTxParams, hasFetchedParams, tariAccount])
9688

9789
useEffect(() => {
98-
setHasFetchedParams(!!tariColdWalletAddress?.length || !!wrapTokenFeePercentageBps)
90+
const hasFetched = Boolean(!!tariColdWalletAddress?.length || !!wrapTokenFeePercentageBps)
91+
onFetchedParams(hasFetched)
9992
}, [tariColdWalletAddress?.length, wrapTokenFeePercentageBps])
10093

10194
useEffect(() => {
102-
if (!tariAccount) return
103-
104-
const fetchUserTransactions = async () => {
105-
try {
106-
await getUserBackendBridgeTxs()
107-
await setTariAccount()
108-
} catch (error) {
109-
console.error('[ TAPPLET-BRIDGE ] Failed to get user transactions:', error)
110-
}
111-
}
112-
113-
fetchUserTransactions()
114-
// Poll every 30 sec
115-
const intervalId = setInterval(fetchUserTransactions, 30000)
116-
95+
// Poll every 5 min
96+
const intervalId = setInterval(fetchUserTransactions, 1000 * 60 * 5)
11797
return () => {
11898
clearInterval(intervalId)
11999
}
120-
// eslint-disable-next-line react-hooks/exhaustive-deps
121-
}, [tariAccount?.address])
100+
}, [fetchUserTransactions])
122101

123102
useEffect(() => {
124-
if (modalOpen && modalStep === 0 && isConnected) {
125-
setModalOpen(false)
103+
if (isModalOpen && modalStep === 0 && isConnected) {
104+
setIsModalOpen(false)
126105
setModalStep(1)
127-
} else if (!showModalDetailedTx && showModalOngoingTx && (isSuccess || ongoingBridgeTx.type === 'wrap')) {
128-
setModalStep(2)
129-
setModalOpen(true)
130-
} else if (showModalDetailedTx && modalOpen) {
131-
setModalOpen(false)
132-
}
133-
}, [isConnected, modalOpen, modalStep, isSuccess, ongoingBridgeTx, showModalDetailedTx, showModalOngoingTx])
134-
135-
useEffect(() => {
136-
if (isUnwrapping) {
137-
console.debug(`[ TAPPLET-BRIDGE ] Initiating transaction...`)
138-
setModalStep(3)
139-
}
140-
}, [isUnwrapping])
141-
142-
useEffect(() => {
143-
if (isSuccess) {
144-
console.debug(`[ TAPPLET-BRIDGE ] Unwrap transaction success!`)
145-
setIsUnwrapping(false)
106+
} else if (!showModalDetailedTx && showModalOngoingTx && (unwrapSuccess || ongoingBridgeTx.type === 'wrap')) {
146107
setModalStep(2)
147-
} else if (isError) {
148-
console.error(`[ TAPPLET-BRIDGE ] Unwrap transaction failed:`, error)
149-
setIsUnwrapping(false)
150-
setIsUnwrappingFailed(true)
108+
setIsModalOpen(true)
109+
} else if (showModalDetailedTx && isModalOpen) {
110+
setIsModalOpen(false)
151111
}
152-
}, [isPending, isSuccess, isError, error])
112+
}, [isConnected, isModalOpen, modalStep, ongoingBridgeTx, showModalDetailedTx, showModalOngoingTx, unwrapSuccess])
153113

154114
useEffect(() => {
155115
if (fromNetwork.name === 'Tari') {
156-
setRemainingDailyLimit(undefined)
116+
onNetworkChange()
157117
return
158118
}
159-
160-
const fetchDailyLimit = async () => {
161-
try {
162-
const limitMicro = await TokensUnwrappedService.getRemainingDailyLimit()
163-
const limitXtm = microXtmToXtm(limitMicro)
164-
setRemainingDailyLimit(limitXtm)
165-
} catch (error) {
166-
console.error('[ TAPPLET-BRIDGE ] Failed to fetch daily limit:', error)
167-
}
168-
}
169-
170-
fetchDailyLimit()
171-
172119
const interval = setInterval(fetchDailyLimit, REFETCH_LIMIT_INTERVAL)
173120
return () => clearInterval(interval)
174-
}, [fromNetwork.name])
121+
}, [fetchDailyLimit, fromNetwork.name])
175122

176-
const handleConnectClick = () => {
177-
if (!isConnected) {
178-
setModalStep(0)
179-
setModalOpen(true)
180-
}
181-
}
182-
183-
const handleContinueClick = () => {
184-
setModalStep(1)
185-
setModalOpen(true)
186-
}
187123
const handleSetOngoingModalOpen = (open: boolean) => {
188-
setModalOpen(open)
124+
setIsModalOpen(open)
189125
if (ongoingBridgeTx) setLastOngoingBridgeTx({ ...ongoingBridgeTx, showModal: false })
190126
}
191-
192-
const handleBridgeToEthereum = useCallback(() => {
193-
if (!amount || !ethAddress) {
194-
return
195-
}
196-
197-
bridgeToEthereum({
198-
amount,
199-
ethAddress: ethAddress,
200-
amountAfterFee: feesData.amountAfterFee,
201-
})
202-
.then(async () => {
203-
await getUserBackendBridgeTxs()
204-
setExceededDailyLimit(false)
205-
})
206-
.catch((e) => {
207-
console.error('[ TAPPLET-BRIDGE ] Bridge operation failed:', e)
208-
const error = e as Error
209-
const isLimitError =
210-
error?.message?.includes(DAILY_LIMIT_ERROR_TYPE) || error?.message?.includes(DAILY_LIMIT_ERROR)
211-
setExceededDailyLimit(isLimitError)
212-
if (isLimitError) {
213-
setModalOpen(false)
214-
}
215-
})
216-
}, [amount, ethAddress, bridgeToEthereum, feesData.amountAfterFee, getUserBackendBridgeTxs, setExceededDailyLimit])
217-
218-
const handleBridgeToTari = useCallback(async () => {
219-
if (!amount || !ethAddress || !tariAccount?.address) {
220-
return
221-
}
222-
223-
setIsUnwrapping(true)
224-
const success = await bridgeToTari(amount, ethAddress, tariAccount.address)
225-
if (success) {
226-
setIsUnwrapping(false)
227-
} else {
228-
setIsUnwrapping(false)
229-
setIsUnwrappingFailed(true)
230-
}
231-
}, [amount, ethAddress, tariAccount?.address, bridgeToTari])
232-
233127
const handleCloseModal = () => {
234128
resetField('amount', { defaultValue: '' })
235-
setIsUnwrappingFailed(false)
129+
setUnwrapFailed(false)
236130
handleSetOngoingModalOpen(false)
237131
setModalStep(1)
238132
}
133+
239134
return (
240135
<main className="relative min-h-screen w-full flex flex-col pl-(--tu-padding-left) pr-8 items-center justify-center">
241-
<Header onConnectClickAction={handleConnectClick} />
242-
243-
<MainComponent
244-
onConnectClick={handleConnectClick}
245-
onContinueClick={handleContinueClick}
246-
control={control}
247-
errors={errors}
248-
setValue={setValue}
249-
isValid={isValid}
250-
fromNetwork={fromNetwork}
251-
setFromNetwork={setFromNetwork}
252-
toNetwork={toNetwork}
253-
setToNetwork={setToNetwork}
254-
remainingDailyLimit={remainingDailyLimit}
255-
/>
256-
257-
{detailedTx && <TransactionDetailsModal transaction={detailedTx} closeModal={() => setDetailedTx(null)} />}
258-
259-
{modalOpen && !showModalDetailedTx && (
260-
<MainModal
261-
success={isWrapSuccess}
262-
failed={isFailed}
263-
step={modalStep}
264-
handleBridgeToEthereum={handleBridgeToEthereum}
265-
handleBridgeToTari={handleBridgeToTari}
266-
amount={amount}
267-
ethereumAddress={ethAddress}
268-
tariWalletAddress={tariAccount?.address}
269-
fromNetwork={fromNetwork}
270-
toNetwork={toNetwork}
271-
feesData={feesData}
272-
closeModal={handleCloseModal}
273-
type={ongoingBridgeTx?.type || 'wrap'}
274-
/>
275-
)}
136+
<Header />
137+
<FormProvider {...methods}>
138+
<MainComponent remainingDailyLimit={remainingDailyLimit} />
139+
{isModalOpen && !showModalDetailedTx && (
140+
<MainModal
141+
success={isWrapSuccess}
142+
failed={isFailed}
143+
step={modalStep}
144+
amount={amount}
145+
ethereumAddress={ethAddress}
146+
tariWalletAddress={tariAccount?.address}
147+
feesData={feesData}
148+
closeModalAction={handleCloseModal}
149+
type={ongoingBridgeTx?.type || 'wrap'}
150+
/>
151+
)}
152+
</FormProvider>
153+
{detailedTx && <TransactionDetailsModal transaction={detailedTx} closeModalAction={() => setDetailedTx(null)} />}
276154
<FooterText />
277155
</main>
278156
)

0 commit comments

Comments
 (0)