Skip to content

Commit

Permalink
Merge pull request #751 from threshold-network/improve-tbtc-sdk-initi…
Browse files Browse the repository at this point in the history
…alization

Improve tBTC SDK initialization
  • Loading branch information
evandrosaturnino committed Jun 5, 2024
2 parents c8249d3 + 8711fc7 commit 586fe84
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 175 deletions.
4 changes: 1 addition & 3 deletions src/components/SubmitTxButton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { FC } from "react"
import { Button, ButtonProps } from "@chakra-ui/react"
import { useIsActive } from "../hooks/useIsActive"
import { useIsTbtcSdkInitializing } from "../contexts/ThresholdContext"
import { useConnectWallet } from "../hooks/useConnectWallet"

interface Props extends ButtonProps {
Expand All @@ -15,14 +14,13 @@ const SubmitTxButton: FC<Props> = ({
...buttonProps
}) => {
const { isActive } = useIsActive()
const { isSdkInitializedWithSigner } = useIsTbtcSdkInitializing()
const connectWallet = useConnectWallet()

const onConnectWalletClick = () => {
connectWallet()
}

if (isActive && isSdkInitializedWithSigner) {
if (isActive) {
return (
<Button mt={6} isFullWidth onClick={onSubmit} {...buttonProps}>
{submitText}
Expand Down
74 changes: 4 additions & 70 deletions src/contexts/ThresholdContext.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
import { TBTC as SDK } from "@keep-network/tbtc-v2.ts"
import { useWeb3React } from "@web3-react/core"
import { providers, Signer } from "ethers"
import {
createContext,
Dispatch,
FC,
SetStateAction,
useCallback,
useContext,
useEffect,
useRef,
useState,
} from "react"
import {
getDefaultThresholdLibProvider,
Expand All @@ -22,76 +18,29 @@ import { useIsEmbed } from "../hooks/useIsEmbed"

const ThresholdContext = createContext(threshold)

// TODO: We should probably put those values information in ThresholdContext,
// but that would require a lot of change through app, so for now we will keep
// it in a separate context.
const IsSdkInitializingContext = createContext({
isSdkInitializing: false,
isSdkInitialized: false,
isSdkInitializedWithSigner: false,
setIsSdkInitializing: (() => {}) as Dispatch<SetStateAction<boolean>>,
})

export const useThreshold = () => {
return useContext(ThresholdContext)
}

export const useIsTbtcSdkInitializing = () => {
return useContext(IsSdkInitializingContext)
}

const useInitializeTbtcSdk = () => {
const [sdk, setSdk] = useState<SDK | undefined>(undefined)
const [isInitializing, setIsInitializing] = useState(false)
const [isInitialized, setIsInitialized] = useState(false)
const [isInitializedWithSigner, setIsInitializedWithSigner] = useState(false)
const threshold = useThreshold()

const initializeSdk = useCallback(
async (providerOrSigner: providers.Provider | Signer, account?: string) => {
if (!isInitializing) {
setIsInitializing(true)
const sdk = await threshold.tbtc.initializeSdk(
providerOrSigner,
account
)
setSdk(sdk)
setIsInitialized(true)
const isInitializedWithSigner = account ? true : false
setIsInitializedWithSigner(isInitializedWithSigner)
setIsInitializing(false)
}
threshold.tbtc.initializeSdk(providerOrSigner, account)
},
[
threshold,
setSdk,
setIsInitializing,
setIsInitialized,
setIsInitializedWithSigner,
]
[threshold]
)

return {
sdk,
isSdkInitializing: isInitializing,
isSdkInitialized: isInitialized,
isSdkInitializedWithSigner: isInitializedWithSigner,
setIsSdkInitializing: setIsInitializing,
initializeSdk,
}
}

export const ThresholdProvider: FC = ({ children }) => {
const { library } = useWeb3React()
const hasThresholdLibConfigBeenUpdated = useRef(false)
const {
sdk,
initializeSdk,
isSdkInitializing,
isSdkInitialized,
isSdkInitializedWithSigner,
setIsSdkInitializing,
} = useInitializeTbtcSdk()
const { initializeSdk } = useInitializeTbtcSdk()
const { ledgerLiveAppEthereumSigner } = useLedgerLiveApp()
const { account, isActive } = useIsActive()
const { isEmbed } = useIsEmbed()
Expand All @@ -107,7 +56,6 @@ export const ThresholdProvider: FC = ({ children }) => {
bitcoin: threshold.config.bitcoin,
})
hasThresholdLibConfigBeenUpdated.current = true
initializeSdk(threshold.config.ethereum.providerOrSigner, account)
}

if (!isActive && hasThresholdLibConfigBeenUpdated.current) {
Expand All @@ -120,26 +68,12 @@ export const ThresholdProvider: FC = ({ children }) => {
bitcoin: threshold.config.bitcoin,
})
hasThresholdLibConfigBeenUpdated.current = false
initializeSdk(threshold.config.ethereum.providerOrSigner)
}

if (!sdk && !isSdkInitializing && !isSdkInitialized) {
initializeSdk(threshold.config.ethereum.providerOrSigner)
}
}, [library, isActive, account, initializeSdk, isEmbed])

return (
<ThresholdContext.Provider value={threshold}>
<IsSdkInitializingContext.Provider
value={{
isSdkInitializing,
isSdkInitialized,
isSdkInitializedWithSigner,
setIsSdkInitializing,
}}
>
{children}
</IsSdkInitializingContext.Provider>
{children}
</ThresholdContext.Provider>
)
}
3 changes: 0 additions & 3 deletions src/hooks/ledger-live-app/useRequestEthereumAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Account, WalletAPIClient } from "@ledgerhq/wallet-api-client"
import { useRequestAccount as useWalletApiRequestAccount } from "@ledgerhq/wallet-api-client-react"
import { useCallback, useEffect } from "react"
import { useLedgerLiveApp } from "../../contexts/LedgerLiveAppContext"
import { useIsTbtcSdkInitializing } from "../../contexts/ThresholdContext"
import { useWalletApiReactTransport } from "../../contexts/TransportProvider"
import { walletConnected } from "../../store/account"
import { supportedChainId } from "../../utils/getEnvVariable"
Expand All @@ -27,7 +26,6 @@ export function useRequestEthereumAccount(): UseRequestAccountReturn {
const useRequestAccountReturn = useWalletApiRequestAccount()
const { account, requestAccount } = useRequestAccountReturn
const dispatch = useAppDispatch()
const { setIsSdkInitializing } = useIsTbtcSdkInitializing()
const { isEmbed } = useIsEmbed()

useEffect(() => {
Expand All @@ -37,7 +35,6 @@ export function useRequestEthereumAccount(): UseRequestAccountReturn {
// here to indicate as early as as possible that the sdk is in the
// initializing process.
if (isEmbed) {
setIsSdkInitializing(true)
setEthAccount(account || undefined)
dispatch(walletConnected(account?.address || ""))
}
Expand Down
9 changes: 1 addition & 8 deletions src/hooks/tbtc/useFetchRedemptionDetails.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { useEffect, useState } from "react"
import {
useIsTbtcSdkInitializing,
useThreshold,
} from "../../contexts/ThresholdContext"
import { useThreshold } from "../../contexts/ThresholdContext"
import {
isValidType,
fromSatoshiToTokenPrecision,
Expand Down Expand Up @@ -43,11 +40,8 @@ export const useFetchRedemptionDetails = (
const [redemptionData, setRedemptionData] = useState<
RedemptionDetails | undefined
>()
const { isSdkInitialized } = useIsTbtcSdkInitializing()

useEffect(() => {
if (!isSdkInitialized) return

if (!redeemer || isEmptyOrZeroAddress(redeemer)) {
setError("Invalid redeemer value.")
return
Expand Down Expand Up @@ -242,7 +236,6 @@ export const useFetchRedemptionDetails = (
threshold,
getBlock,
findRedemptionInBitcoinTx,
isSdkInitialized,
])

return { isFetching, data: redemptionData, error }
Expand Down
5 changes: 1 addition & 4 deletions src/hooks/useFetchTvl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { useETHData } from "./useETHData"
import { useToken } from "./useToken"
import { Token } from "../enums"
import { toUsdBalance } from "../utils/getUsdBalance"
import { useIsTbtcSdkInitializing } from "../contexts/ThresholdContext"

interface TvlRawData {
ecdsaTvl: string
Expand Down Expand Up @@ -62,7 +61,6 @@ export const useFetchTvl = (): [
const tTokenStaking = useTStakingContract()
const keepTokenStaking = useKeepTokenStakingContract()
const tBTCToken = useToken(Token.TBTCV2)
const { isSdkInitializing } = useIsTbtcSdkInitializing()

const fetchOnChainData = useMulticall([
{
Expand Down Expand Up @@ -96,7 +94,6 @@ export const useFetchTvl = (): [
])

const fetchTvlData = useCallback(async () => {
if (isSdkInitializing) return initialState
const chainData = await fetchOnChainData()
if (chainData.length === 0) return initialState

Expand All @@ -118,7 +115,7 @@ export const useFetchTvl = (): [
setRawData(data)

return data
}, [fetchOnChainData, isSdkInitializing])
}, [fetchOnChainData])

const data = useMemo(() => {
const ecdsa = toUsdBalance(formatUnits(ecdsaTvl), eth.usdPrice)
Expand Down
3 changes: 0 additions & 3 deletions src/hooks/useIsActive.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useWeb3React } from "@web3-react/core"
import { useCallback, useMemo } from "react"
import { useLedgerLiveApp } from "../contexts/LedgerLiveAppContext"
import { useIsTbtcSdkInitializing } from "../contexts/ThresholdContext"
import { supportedChainId } from "../utils/getEnvVariable"
import { useIsEmbed } from "./useIsEmbed"

Expand All @@ -27,7 +26,6 @@ export const useIsActive = (): UseIsActiveResult => {
const { ethAccount, setEthAccount } = useLedgerLiveApp()
const ledgerLiveAppEthAddress = ethAccount?.address || undefined
const { isEmbed } = useIsEmbed()
const { setIsSdkInitializing } = useIsTbtcSdkInitializing()

const isActive = useMemo(() => {
if (isEmbed) {
Expand All @@ -37,7 +35,6 @@ export const useIsActive = (): UseIsActiveResult => {
}, [ledgerLiveAppEthAddress, _active, _account, isEmbed])

const deactivateLedgerLiveApp = useCallback(() => {
setIsSdkInitializing(true)
setEthAccount(undefined)
}, [setEthAccount])

Expand Down
56 changes: 20 additions & 36 deletions src/pages/tBTC/Bridge/Mint.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,7 @@ import {
} from "./BridgeLayout"
import { BridgeProcessEmptyState } from "./components/BridgeProcessEmptyState"
import { MintDurationWidget } from "../../../components/MintDurationWidget"
import {
useIsTbtcSdkInitializing,
useThreshold,
} from "../../../contexts/ThresholdContext"
import { useThreshold } from "../../../contexts/ThresholdContext"

export const MintPage: PageComponent = ({}) => {
return <Outlet />
Expand All @@ -30,8 +27,6 @@ export const MintingFormPage: PageComponent = ({ ...props }) => {
const { tBTCDepositData } = useTBTCDepositDataFromLocalStorage()
const { btcDepositAddress, updateState } = useTbtcState()
const { account } = useIsActive()
const { isSdkInitializing, isSdkInitializedWithSigner } =
useIsTbtcSdkInitializing()

useEffect(() => {
// Update the store with the deposit data if the account is placed in tbtc
Expand All @@ -43,38 +38,27 @@ export const MintingFormPage: PageComponent = ({ ...props }) => {
isSameETHAddress(tBTCDepositData[account].ethAddress, account) &&
tBTCDepositData[account].btcDepositAddress !== btcDepositAddress
) {
// When the code enters this if, this means that the deposit data is
// placed in tBTC local storage and we need to update the store with that
// data. The SDK might still be initializing though, so we should show the
// loading state as soon as possible. That's why we are setting the
// `mintingStep` as undefined when we notice that sdk is initializing -
// this will display a loading state for the minting flow, and then
// redirect to the correct step.
if (isSdkInitializing) updateState("mintingStep", undefined)

if (!isSdkInitializing && isSdkInitializedWithSigner) {
const {
btcDepositAddress,
ethAddress,
blindingFactor,
btcRecoveryAddress,
walletPublicKeyHash,
refundLocktime,
} = tBTCDepositData[account]
const {
btcDepositAddress,
ethAddress,
blindingFactor,
btcRecoveryAddress,
walletPublicKeyHash,
refundLocktime,
} = tBTCDepositData[account]

updateState("ethAddress", ethAddress)
updateState("blindingFactor", blindingFactor)
updateState("btcRecoveryAddress", btcRecoveryAddress)
updateState("walletPublicKeyHash", walletPublicKeyHash)
updateState("refundLocktime", refundLocktime)
// We reset the minting step to undefined to show skeleton and the
// useEffect in MintingFlowRouter will update and set the proper minting
// step when it recognizes the "btcDepositAddress" change.
updateState("mintingStep", undefined)
updateState("btcDepositAddress", btcDepositAddress)
}
updateState("ethAddress", ethAddress)
updateState("blindingFactor", blindingFactor)
updateState("btcRecoveryAddress", btcRecoveryAddress)
updateState("walletPublicKeyHash", walletPublicKeyHash)
updateState("refundLocktime", refundLocktime)
// We reset the minting step to undefined to show skeleton and the
// useEffect in MintingFlowRouter will update and set the proper minting
// step when it recognizes the "btcDepositAddress" change.
updateState("mintingStep", undefined)
updateState("btcDepositAddress", btcDepositAddress)
}
}, [account, isSdkInitializing, isSdkInitializedWithSigner])
}, [account])

return <MintingFlowRouter />
}
Expand Down
18 changes: 2 additions & 16 deletions src/pages/tBTC/Bridge/Minting/MintingFlowRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,13 @@ import { BridgeProcessCardTitle } from "../components/BridgeProcessCardTitle"
import { useRemoveDepositData } from "../../../../hooks/tbtc/useRemoveDepositData"
import { useAppDispatch } from "../../../../hooks/store"
import { tbtcSlice } from "../../../../store/tbtc"
import { useIsTbtcSdkInitializing } from "../../../../contexts/ThresholdContext"

const MintingFlowRouterBase = () => {
const dispatch = useAppDispatch()
const { account } = useIsActive()
const { mintingStep, updateState, btcDepositAddress, utxo } = useTbtcState()
const removeDepositData = useRemoveDepositData()
const { openModal } = useModal()
const { isSdkInitializing, isSdkInitializedWithSigner } =
useIsTbtcSdkInitializing()

const onPreviousStepClick = (previousStep?: MintingStep) => {
if (mintingStep === MintingStep.MintingSuccess) {
Expand All @@ -39,24 +36,13 @@ const MintingFlowRouterBase = () => {
}

useEffect(() => {
if (
!btcDepositAddress ||
!account ||
isSdkInitializing ||
!isSdkInitializedWithSigner
) {
if (!btcDepositAddress || !account) {
return
}
dispatch(
tbtcSlice.actions.findUtxo({ btcDepositAddress, depositor: account })
)
}, [
btcDepositAddress,
account,
dispatch,
isSdkInitializing,
isSdkInitializedWithSigner,
])
}, [btcDepositAddress, account, dispatch])

switch (mintingStep) {
case MintingStep.ProvideData: {
Expand Down
Loading

0 comments on commit 586fe84

Please sign in to comment.