Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
onghwan committed Sep 18, 2024
1 parent 1547ec1 commit 3b910b6
Show file tree
Hide file tree
Showing 34 changed files with 911 additions and 2,890 deletions.
223 changes: 4 additions & 219 deletions packages/core-mobile/app/contexts/BridgeContext.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,12 @@
import React, {
createContext,
ReactNode,
useCallback,
useContext,
useEffect,
useRef
} from 'react'
import React, { ReactNode, useEffect } from 'react'
import {
BridgeSDKProvider,
BridgeTransaction,
getMinimumConfirmations,
trackBridgeTransaction,
TrackerSubscription,
useBridgeSDK
} from '@avalabs/core-bridge-sdk'
import { useDispatch, useSelector } from 'react-redux'
import { selectActiveAccount } from 'store/account'
import {
addBridgeTransaction,
popBridgeTransaction,
selectBridgeConfig,
selectBridgeTransactions
} from 'store/bridge'
import {
useAvalancheProvider,
useBitcoinProvider,
useEthereumProvider
} from 'hooks/networks/networkProviderHooks'
import { useSelector } from 'react-redux'
import { selectBridgeConfig } from 'store/bridge'
import { isEqual } from 'lodash'
import { Network } from '@avalabs/core-chains-sdk'
import Logger from 'utils/Logger'
import { showSnackBarCustom } from 'components/Snackbar'
import TransactionToast, {
TransactionToastType
} from 'components/toast/TransactionToast'
import AnalyticsService from 'services/analytics/AnalyticsService'
import BridgeService from 'services/bridge/BridgeService'
import { selectIsDeveloperMode } from 'store/settings/advanced'

Expand All @@ -48,15 +20,6 @@ export type PartialBridgeTransaction = Pick<
| 'symbol'
>

interface BridgeContext {
createBridgeTransaction(
tx: PartialBridgeTransaction,
network: Network
): Promise<void | { error: string }>
}

const bridgeContext = createContext<BridgeContext>({} as BridgeContext)

export function BridgeProvider({
children
}: {
Expand All @@ -69,60 +32,20 @@ export function BridgeProvider({
)
}

export function useBridgeContext(): BridgeContext {
return useContext(bridgeContext)
}

const TrackerSubscriptions = new Map<string, TrackerSubscription>()

function LocalBridgeProvider({
children
}: {
children: ReactNode
}): JSX.Element {
const dispatch = useDispatch()
const bridgeConfig = useSelector(selectBridgeConfig)
const config = bridgeConfig?.config
const activeAccount = useSelector(selectActiveAccount)
const bridgeTransactions = useSelector(selectBridgeTransactions)
const ethereumProvider = useEthereumProvider()
const bitcoinProvider = useBitcoinProvider()
const avalancheProvider = useAvalancheProvider()
const { bridgeConfig: bridgeConfigSDK, setBridgeConfig } = useBridgeSDK()
const isToastVisible = useRef<boolean>()

const isDeveloperMode = useSelector(selectIsDeveloperMode)

useEffect(() => {
BridgeService.setBridgeEnvironment(isDeveloperMode)
}, [isDeveloperMode])

const removeBridgeTransaction = useCallback(
(tx: BridgeTransaction) => {
dispatch(popBridgeTransaction(tx.sourceTxHash))
AnalyticsService.capture('BridgeTransferRequestSucceeded')

if (!isToastVisible.current) {
isToastVisible.current = true

showSnackBarCustom({
component: (
<TransactionToast
message={'Bridge Successful'}
type={TransactionToastType.SUCCESS}
txHash={tx.sourceTxHash}
/>
),
duration: 'short',
onClose: () => {
isToastVisible.current = false
}
})
}
},
[dispatch]
)

useEffect(() => {
// sync bridge config in bridge sdk with ours
// this is necessary because:
Expand All @@ -134,143 +57,5 @@ function LocalBridgeProvider({
}
}, [bridgeConfig, bridgeConfigSDK, setBridgeConfig])

// init tracking updates for txs
const subscribeToTransaction = useCallback(
async (trackedTransaction: BridgeTransaction) => {
if (
trackedTransaction &&
config &&
!TrackerSubscriptions.has(trackedTransaction.sourceTxHash) &&
avalancheProvider &&
ethereumProvider
) {
// Start transaction tracking process (no need to await)
try {
const subscription = trackBridgeTransaction({
bridgeTransaction: trackedTransaction,
onBridgeTransactionUpdate: (tx: BridgeTransaction) => {
// Update the transaction, even if it's complete
// (we want to keep the tx up to date, because some Component(i.e. BridgeTransactionStatus) has local state that depends on it)
dispatch(addBridgeTransaction(tx))

if (tx.complete) {
removeBridgeTransaction(tx)
}
},
config,
avalancheProvider,
ethereumProvider,
bitcoinProvider
})

TrackerSubscriptions.set(
trackedTransaction.sourceTxHash,
subscription
)
} catch (e) {
Logger.error('failed to subscribe to transaction', e)
}
}
},
[
avalancheProvider,
bitcoinProvider,
config,
dispatch,
ethereumProvider,
removeBridgeTransaction
]
)

/**
* Add a new pending bridge transaction to the background state and start the
* transaction tracking process.
*/
const createBridgeTransaction = useCallback(
async (
partialBridgeTransaction: PartialBridgeTransaction,
network: Network
) => {
if (!config || !network || !activeAccount) {
return Promise.reject('Wallet not ready')
}

const {
sourceChain,
sourceTxHash,
sourceStartedAt,
targetChain,
amount,
symbol
} = partialBridgeTransaction

const addressC = activeAccount.addressC
const addressBTC = activeAccount.addressBTC

if (!addressBTC) return { error: 'missing addressBTC' }
if (!addressC) return { error: 'missing addressC' }
if (!sourceChain) return { error: 'missing sourceChain' }
if (!sourceTxHash) return { error: 'missing sourceTxHash' }
if (!sourceStartedAt) return { error: 'missing sourceStartedAt' }
if (!targetChain) return { error: 'missing targetChain' }
if (!amount) return { error: 'missing amount' }
if (!symbol) return { error: 'missing symbol' }
if (!config) return { error: 'missing bridge config' }
if (bridgeTransactions[sourceTxHash])
return { error: 'bridge tx already exists' }
const requiredConfirmationCount = getMinimumConfirmations(
sourceChain,
config
)

const environment = network.isTestnet ? 'test' : 'main'

const bridgeTransaction: BridgeTransaction = {
/* from params */
sourceChain,
sourceTxHash,
sourceStartedAt,
targetChain,
amount,
symbol,
/* new fields */
addressC,
addressBTC,
complete: false,
confirmationCount: 0,
environment,
requiredConfirmationCount
}

dispatch(addBridgeTransaction(bridgeTransaction))
subscribeToTransaction(bridgeTransaction)
},
[
activeAccount,
bridgeTransactions,
config,
dispatch,
subscribeToTransaction
]
)

// load pending txs from storage
useEffect(() => {
Object.values(bridgeTransactions).forEach(tx => {
if (tx.complete) {
removeBridgeTransaction(tx)
} else {
subscribeToTransaction(tx)
}
})
}, [bridgeTransactions, subscribeToTransaction, removeBridgeTransaction])

return (
<bridgeContext.Provider
value={{
createBridgeTransaction
}}>
{children}
</bridgeContext.Provider>
)
return <>{children}</>
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { selectIsDeveloperMode } from 'store/settings/advanced'
import { getNetworkContractTokens } from './utils/getNetworkContractTokens'

export const useNetworkContractTokens = (
network: Network
network: Network | undefined
): NetworkContractToken[] => {
const allCustomTokens = useSelector(selectAllCustomTokens)
const isDeveloperMode = useSelector(selectIsDeveloperMode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import ModuleManager from 'vmModule/ModuleManager'
import { mapToVmNetwork } from 'vmModule/utils/mapToVmNetwork'

export const getNetworkContractTokens = async (
network: Network
network: Network | undefined
): Promise<NetworkContractToken[]> => {
if (!network) return []

const module = await ModuleManager.loadModuleByNetwork(network)

return module.getTokens(mapToVmNetwork(network))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { AssetBalance } from 'screens/bridge/utils/types'
import { useSelector } from 'react-redux'
import { selectIsBridgeBlocked } from 'store/posthog'
import AnalyticsService from 'services/analytics/AnalyticsService'
import BridgeUniversal from 'screens/bridge/BridgeUniversal'
import Bridge from 'screens/bridge/Bridge'

export type BridgeStackParamList = {
[AppNavigation.Bridge.Bridge]: { initialTokenSymbol: string } | undefined
Expand Down Expand Up @@ -46,7 +46,7 @@ function BridgeScreenStack(): JSX.Element {
...MainHeaderOptions()
}}
name={AppNavigation.Bridge.Bridge}
component={BridgeUniversal}
component={Bridge}
/>
<BridgeStack.Screen
options={{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
import {
Blockchain,
BridgeTransaction,
useBridgeSDK
} from '@avalabs/core-bridge-sdk'
import { Blockchain, useBridgeSDK } from '@avalabs/core-bridge-sdk'
import {
getBlockchainDisplayName,
isPendingBridgeTransaction
Expand All @@ -16,9 +12,7 @@ import { useNetworks } from 'hooks/networks/useNetworks'
* Get the source and target blockchain names to display a Bridge transaction.
* @param tx Assumed to be a Bridge transaction for the active network
*/
export function useBlockchainNames(
tx: Transaction | BridgeTransaction | BridgeTransfer
): {
export function useBlockchainNames(tx: Transaction | BridgeTransfer): {
sourceBlockchain: string
targetBlockchain: string
} {
Expand Down
Loading

0 comments on commit 3b910b6

Please sign in to comment.