diff --git a/alm/src/hooks/useMessageConfirmations.ts b/alm/src/hooks/useMessageConfirmations.ts index a7a204fc..84efc2f9 100644 --- a/alm/src/hooks/useMessageConfirmations.ts +++ b/alm/src/hooks/useMessageConfirmations.ts @@ -11,9 +11,6 @@ import { VALIDATOR_CONFIRMATION_STATUS } from '../config/constants' import { homeBlockNumberProvider, foreignBlockNumberProvider } from '../services/BlockNumberProvider' -import { checkSignaturesWaitingForBLocks } from '../utils/signatureWaitingForBlocks' -import { getCollectedSignaturesEvent } from '../utils/getCollectedSignaturesEvent' -import { checkWaitingBlocksForExecution } from '../utils/executionWaitingForBlocks' import { getConfirmationsForTx } from '../utils/getConfirmationsForTx' import { getFinalizationEvent } from '../utils/getFinalizationEvent' import { @@ -64,11 +61,11 @@ export const useMessageConfirmations = ({ blockConfirmations }: useMessageConfirmationsParams) => { const { home, foreign } = useStateProvider() - const [confirmations, setConfirmations] = useState([]) + const [confirmations, setConfirmations] = useState([]) const [status, setStatus] = useState(CONFIRMATIONS_STATUS.UNDEFINED) const [waitingBlocks, setWaitingBlocks] = useState(false) const [waitingBlocksResolved, setWaitingBlocksResolved] = useState(false) - const [signatureCollected, setSignatureCollected] = useState(false) + const [signatureCollected, setSignatureCollected] = useState(false) const [executionEventsFetched, setExecutionEventsFetched] = useState(false) const [collectedSignaturesEvent, setCollectedSignaturesEvent] = useState>(null) const [executionData, setExecutionData] = useState({ @@ -85,12 +82,10 @@ export const useMessageConfirmations = ({ const [pendingConfirmations, setPendingConfirmations] = useState(false) const [pendingExecution, setPendingExecution] = useState(false) - const existsConfirmation = (confirmationArray: ConfirmationParam[]) => { - const filteredList = confirmationArray.filter( + const existsConfirmation = (confirmationArray: ConfirmationParam[]) => + confirmationArray.some( c => c.status !== VALIDATOR_CONFIRMATION_STATUS.UNDEFINED && c.status !== VALIDATOR_CONFIRMATION_STATUS.WAITING ) - return filteredList.length > 0 - } // start watching blocks at the start useEffect( @@ -108,129 +103,154 @@ export const useMessageConfirmations = ({ () => { if (!receipt || !blockConfirmations || waitingBlocksResolved) return - const subscriptions: Array = [] - - const unsubscribe = () => { - subscriptions.forEach(s => { - clearTimeout(s) - }) - } + let timeoutId: number const blockProvider = fromHome ? homeBlockNumberProvider : foreignBlockNumberProvider const interval = fromHome ? HOME_RPC_POLLING_INTERVAL : FOREIGN_RPC_POLLING_INTERVAL const targetBlock = receipt.blockNumber + blockConfirmations + const validatorsWaiting = validatorList.map(validator => ({ + validator, + status: VALIDATOR_CONFIRMATION_STATUS.WAITING, + txHash: '', + timestamp: 0 + })) - checkSignaturesWaitingForBLocks( - targetBlock, - setWaitingBlocks, - setWaitingBlocksResolved, - validatorList, - setConfirmations, - blockProvider, - interval, - subscriptions - ) + const checkSignaturesWaitingForBLocks = () => { + const currentBlock = blockProvider.get() - return () => { - unsubscribe() + if (currentBlock && currentBlock >= targetBlock) { + setWaitingBlocksResolved(true) + setWaitingBlocks(false) + } else if (currentBlock) { + setWaitingBlocks(true) + setConfirmations(validatorsWaiting) + timeoutId = setTimeout(checkSignaturesWaitingForBLocks, interval) + } else { + timeoutId = setTimeout(checkSignaturesWaitingForBLocks, 500) + } } + + checkSignaturesWaitingForBLocks() + + return () => clearTimeout(timeoutId) }, - [ - blockConfirmations, - foreign.web3, - fromHome, - validatorList, - home.web3, - receipt, - setConfirmations, - waitingBlocksResolved - ] + [blockConfirmations, fromHome, receipt, validatorList, waitingBlocksResolved] ) // The collected signature event is only fetched once the signatures are collected on tx from home to foreign, to calculate if // the execution tx on the foreign network is waiting for block confirmations // This is executed if the message is in Home to Foreign direction only + const hasCollectedSignatures = !!signatureCollected // true or string[] useEffect( () => { - if (!fromHome || !receipt || !home.web3 || !signatureCollected) return + if (!fromHome || !receipt || !home.web3 || !home.bridgeContract || !hasCollectedSignatures) return - const subscriptions: Array = [] + let timeoutId: number + let isCancelled = false - const unsubscribe = () => { - subscriptions.forEach(s => { - clearTimeout(s) - }) + const messageHash = home.web3.utils.soliditySha3Raw(message.data) + const contract = home.bridgeContract + + const getCollectedSignaturesEvent = async (fromBlock: number, toBlock: number) => { + const currentBlock = homeBlockNumberProvider.get() + + if (currentBlock) { + // prevent errors if the toBlock parameter is bigger than the latest + const securedToBlock = toBlock >= currentBlock ? currentBlock : toBlock + const events = await contract.getPastEvents('CollectedSignatures', { + fromBlock, + toBlock: securedToBlock + }) + const event = events.find(e => e.returnValues.messageHash === messageHash) + if (event) { + setCollectedSignaturesEvent(event) + } else if (!isCancelled) { + timeoutId = setTimeout(() => getCollectedSignaturesEvent(securedToBlock, securedToBlock + BLOCK_RANGE), 500) + } + } else if (!isCancelled) { + timeoutId = setTimeout(() => getCollectedSignaturesEvent(fromBlock, toBlock), 500) + } } - const fromBlock = receipt.blockNumber - const toBlock = fromBlock + BLOCK_RANGE - const messageHash = home.web3.utils.soliditySha3Raw(message.data) - - getCollectedSignaturesEvent( - home.web3, - home.bridgeContract, - fromBlock, - toBlock, - messageHash, - setCollectedSignaturesEvent, - subscriptions - ) + getCollectedSignaturesEvent(receipt.blockNumber, receipt.blockNumber + BLOCK_RANGE) return () => { - unsubscribe() + clearTimeout(timeoutId) + isCancelled = true } }, - [fromHome, home.bridgeContract, home.web3, message.data, receipt, signatureCollected] + [fromHome, home.bridgeContract, home.web3, message.data, receipt, hasCollectedSignatures] ) // Check if the responsible validator is waiting for block confirmations to execute the message on foreign network // This is executed if the message is in Home to Foreign direction only useEffect( () => { - if (!fromHome || !home.web3 || !receipt || !collectedSignaturesEvent || !blockConfirmations) return + if (!fromHome || !home.web3 || !collectedSignaturesEvent || !blockConfirmations) return if (waitingBlocksForExecutionResolved) return - const subscriptions: Array = [] - - const unsubscribe = () => { - subscriptions.forEach(s => { - clearTimeout(s) - }) - } + let timeoutId: number const targetBlock = collectedSignaturesEvent.blockNumber + blockConfirmations - checkWaitingBlocksForExecution( - homeBlockNumberProvider, - HOME_RPC_POLLING_INTERVAL, - targetBlock, - collectedSignaturesEvent, - setWaitingBlocksForExecution, - setWaitingBlocksForExecutionResolved, - setExecutionData, - subscriptions - ) + const checkWaitingBlocksForExecution = () => { + const currentBlock = homeBlockNumberProvider.get() - return () => { - unsubscribe() + if (currentBlock && currentBlock >= targetBlock) { + const undefinedExecutionState = { + status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED, + validator: collectedSignaturesEvent.returnValues.authorityResponsibleForRelay, + txHash: '', + timestamp: 0, + executionResult: false + } + setExecutionData( + (data: any) => + data.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || + data.status === VALIDATOR_CONFIRMATION_STATUS.WAITING + ? undefinedExecutionState + : data + ) + setWaitingBlocksForExecutionResolved(true) + setWaitingBlocksForExecution(false) + } else if (currentBlock) { + setWaitingBlocksForExecution(true) + const waitingExecutionState = { + status: VALIDATOR_CONFIRMATION_STATUS.WAITING, + validator: collectedSignaturesEvent.returnValues.authorityResponsibleForRelay, + txHash: '', + timestamp: 0, + executionResult: false + } + setExecutionData( + (data: any) => + data.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || + data.status === VALIDATOR_CONFIRMATION_STATUS.WAITING + ? waitingExecutionState + : data + ) + timeoutId = setTimeout(() => checkWaitingBlocksForExecution(), HOME_RPC_POLLING_INTERVAL) + } else { + timeoutId = setTimeout(() => checkWaitingBlocksForExecution(), 500) + } } + + checkWaitingBlocksForExecution() + + return () => clearTimeout(timeoutId) }, - [collectedSignaturesEvent, fromHome, blockConfirmations, home.web3, receipt, waitingBlocksForExecutionResolved] + [collectedSignaturesEvent, fromHome, blockConfirmations, home.web3, waitingBlocksForExecutionResolved] ) // Checks if validators verified the message // To avoid making extra requests, this is only executed when validators finished waiting for blocks confirmations useEffect( () => { - if (!waitingBlocksResolved || !homeStartBlock || !requiredSignatures) return + if (!waitingBlocksResolved || !homeStartBlock || !requiredSignatures || !home.web3 || !home.bridgeContract) return + if (!validatorList || !validatorList.length) return - const subscriptions: Array = [] - - const unsubscribe = () => { - subscriptions.forEach(s => { - clearTimeout(s) - }) - } + let timeoutId: number + let isCancelled = false getConfirmationsForTx( message.data, @@ -241,8 +261,8 @@ export const useMessageConfirmations = ({ setConfirmations, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + id => (timeoutId = id), + () => isCancelled, homeStartBlock, getValidatorFailedTransactionsForMessage, setFailedConfirmations, @@ -252,7 +272,8 @@ export const useMessageConfirmations = ({ ) return () => { - unsubscribe() + clearTimeout(timeoutId) + isCancelled = true } }, [ @@ -263,8 +284,7 @@ export const useMessageConfirmations = ({ home.bridgeContract, requiredSignatures, waitingBlocksResolved, - homeStartBlock, - setConfirmations + homeStartBlock ] ) @@ -274,32 +294,23 @@ export const useMessageConfirmations = ({ useEffect( () => { if ((fromHome && !waitingBlocksForExecutionResolved) || (!fromHome && !waitingBlocksResolved)) return - const startBlock = fromHome ? foreignStartBlock : homeStartBlock - if (!startBlock) return - const subscriptions: Array = [] - - const unsubscribe = () => { - subscriptions.forEach(s => { - clearTimeout(s) - }) - } - - const contractEvent = fromHome ? 'RelayedMessage' : 'AffirmationCompleted' const bridgeContract = fromHome ? foreign.bridgeContract : home.bridgeContract - const providedWeb3 = fromHome ? foreign.web3 : home.web3 - const interval = fromHome ? FOREIGN_RPC_POLLING_INTERVAL : HOME_RPC_POLLING_INTERVAL + const web3 = fromHome ? foreign.web3 : home.web3 + const startBlock = fromHome ? foreignStartBlock : homeStartBlock + if (!startBlock || !bridgeContract || !web3) return + + let timeoutId: number + let isCancelled = false getFinalizationEvent( fromHome, bridgeContract, - contractEvent, - providedWeb3, + web3, setExecutionData, - waitingBlocksResolved, message, - interval, - subscriptions, + id => (timeoutId = id), + () => isCancelled, startBlock, collectedSignaturesEvent, getExecutionFailedTransactionForMessage, @@ -310,7 +321,8 @@ export const useMessageConfirmations = ({ ) return () => { - unsubscribe() + clearTimeout(timeoutId) + isCancelled = true } }, [ diff --git a/alm/src/hooks/useTransactionFinder.ts b/alm/src/hooks/useTransactionFinder.ts index 80611d62..a92f12e2 100644 --- a/alm/src/hooks/useTransactionFinder.ts +++ b/alm/src/hooks/useTransactionFinder.ts @@ -11,40 +11,23 @@ export const useTransactionFinder = ({ txHash, web3 }: { txHash: string; web3: M () => { if (!txHash || !web3) return - const subscriptions: number[] = [] + let timeoutId: number - const unsubscribe = () => { - subscriptions.forEach(s => { - clearTimeout(s) - }) - } - - const getReceipt = async ( - web3: Web3, - txHash: string, - setReceipt: Function, - setStatus: Function, - subscriptions: number[] - ) => { + const getReceipt = async () => { const txReceipt = await web3.eth.getTransactionReceipt(txHash) setReceipt(txReceipt) if (!txReceipt) { setStatus(TRANSACTION_STATUS.NOT_FOUND) - const timeoutId = setTimeout( - () => getReceipt(web3, txHash, setReceipt, setStatus, subscriptions), - HOME_RPC_POLLING_INTERVAL - ) - subscriptions.push(timeoutId) + timeoutId = setTimeout(getReceipt, HOME_RPC_POLLING_INTERVAL) } else { setStatus(TRANSACTION_STATUS.FOUND) } } - getReceipt(web3, txHash, setReceipt, setStatus, subscriptions) - return () => { - unsubscribe() - } + getReceipt() + + return () => clearTimeout(timeoutId) }, [txHash, web3] ) diff --git a/alm/src/hooks/useTransactionStatus.ts b/alm/src/hooks/useTransactionStatus.ts index 44763f54..9d03581a 100644 --- a/alm/src/hooks/useTransactionStatus.ts +++ b/alm/src/hooks/useTransactionStatus.ts @@ -31,19 +31,14 @@ export const useTransactionStatus = ({ useEffect( () => { - const subscriptions: Array = [] + if (!chainId || !txHash || !home.chainId || !foreign.chainId || !home.web3 || !foreign.web3) return + const isHome = chainId === home.chainId + const web3 = isHome ? home.web3 : foreign.web3 - const unsubscribe = () => { - subscriptions.forEach(s => { - clearTimeout(s) - }) - } + let timeoutId: number const getReceipt = async () => { - if (!chainId || !txHash || !home.chainId || !foreign.chainId || !home.web3 || !foreign.web3) return setLoading(true) - const isHome = chainId === home.chainId - const web3 = isHome ? home.web3 : foreign.web3 let txReceipt @@ -59,8 +54,7 @@ export const useTransactionStatus = ({ setStatus(TRANSACTION_STATUS.NOT_FOUND) setDescription(getTransactionStatusDescription(TRANSACTION_STATUS.NOT_FOUND)) setMessages([{ id: txHash, data: '' }]) - const timeoutId = setTimeout(() => getReceipt(), HOME_RPC_POLLING_INTERVAL) - subscriptions.push(timeoutId) + timeoutId = setTimeout(() => getReceipt(), HOME_RPC_POLLING_INTERVAL) } else { const blockNumber = txReceipt.blockNumber const block = await getBlock(web3, blockNumber) @@ -70,9 +64,9 @@ export const useTransactionStatus = ({ if (txReceipt.status) { let bridgeMessages: Array if (isHome) { - bridgeMessages = getHomeMessagesFromReceipt(txReceipt, home.web3, home.bridgeAddress) + bridgeMessages = getHomeMessagesFromReceipt(txReceipt, web3, home.bridgeAddress) } else { - bridgeMessages = getForeignMessagesFromReceipt(txReceipt, foreign.web3, foreign.bridgeAddress) + bridgeMessages = getForeignMessagesFromReceipt(txReceipt, web3, foreign.bridgeAddress) } if (bridgeMessages.length === 0) { @@ -98,14 +92,9 @@ export const useTransactionStatus = ({ setLoading(false) } - // unsubscribe from previous txHash - unsubscribe() - getReceipt() - return () => { - // unsubscribe when unmount component - unsubscribe() - } + + return () => clearTimeout(timeoutId) }, [ txHash, diff --git a/alm/src/utils/__tests__/getConfirmationsForTx.test.ts b/alm/src/utils/__tests__/getConfirmationsForTx.test.ts index 3d21a46e..689bb8d1 100644 --- a/alm/src/utils/__tests__/getConfirmationsForTx.test.ts +++ b/alm/src/utils/__tests__/getConfirmationsForTx.test.ts @@ -34,7 +34,7 @@ const bridgeContract = { } } as Contract const requiredSignatures = 2 -const waitingBlocksResolved = true +const isCancelled = () => false let subscriptions: Array = [] const timestamp = 1594045859 const getFailedTransactions = (): Promise => Promise.resolve([]) @@ -94,8 +94,8 @@ describe('getConfirmationsForTx', () => { setResult, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, getFailedTransactions, setFailedConfirmations, @@ -177,8 +177,8 @@ describe('getConfirmationsForTx', () => { setResult, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, getFailedTransactions, setFailedConfirmations, @@ -241,8 +241,8 @@ describe('getConfirmationsForTx', () => { setResult, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, getFailedTransactions, setFailedConfirmations, @@ -340,8 +340,8 @@ describe('getConfirmationsForTx', () => { setResult, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, getFailedTransactions, setFailedConfirmations, @@ -453,8 +453,8 @@ describe('getConfirmationsForTx', () => { setResult, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, getFailedTransactions, setFailedConfirmations, @@ -557,8 +557,8 @@ describe('getConfirmationsForTx', () => { setResult, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, getFailedTransactions, setFailedConfirmations, @@ -678,8 +678,8 @@ describe('getConfirmationsForTx', () => { setResult, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, getFailedTransactions, setFailedConfirmations, @@ -746,8 +746,8 @@ describe('getConfirmationsForTx', () => { setResult, requiredSignatures, setSignatureCollected, - waitingBlocksResolved, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, getFailedTransactions, setFailedConfirmations, diff --git a/alm/src/utils/__tests__/getFinalizationEvent.test.ts b/alm/src/utils/__tests__/getFinalizationEvent.test.ts index e5eec296..ae9c4100 100644 --- a/alm/src/utils/__tests__/getFinalizationEvent.test.ts +++ b/alm/src/utils/__tests__/getFinalizationEvent.test.ts @@ -4,7 +4,6 @@ import Web3 from 'web3' import { getFinalizationEvent } from '../getFinalizationEvent' import { VALIDATOR_CONFIRMATION_STATUS } from '../../config/constants' -const eventName = 'RelayedMessage' const timestamp = 1594045859 const validator1 = '0x45b96809336A8b714BFbdAB3E4B5e0fe5d839908' const txHash = '0xdab36c9210e7e45fb82af10ffe4960461e41661dce0c9cd36b2843adaa1df156' @@ -20,12 +19,11 @@ const web3 = ({ toChecksumAddress: (a: string) => a } } as unknown) as Web3 -const waitingBlocksResolved = true const message = { id: '0x123', data: '0x123456789' } -const interval = 10000 +const isCancelled = () => false let subscriptions: Array = [] const event = { @@ -66,13 +64,11 @@ describe('getFinalizationEvent', () => { await getFinalizationEvent( true, contract, - eventName, web3, setResult, - waitingBlocksResolved, message, - interval, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, collectedSignaturesEvent, getFailedExecution, @@ -118,13 +114,11 @@ describe('getFinalizationEvent', () => { await getFinalizationEvent( true, contract, - eventName, web3, setResult, - waitingBlocksResolved, message, - interval, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, collectedSignaturesEvent, getFailedExecution, @@ -170,13 +164,11 @@ describe('getFinalizationEvent', () => { await getFinalizationEvent( true, contract, - eventName, web3, setResult, - waitingBlocksResolved, message, - interval, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, collectedSignaturesEvent, getFailedExecution, @@ -222,13 +214,11 @@ describe('getFinalizationEvent', () => { await getFinalizationEvent( true, contract, - eventName, web3, setResult, - waitingBlocksResolved, message, - interval, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, collectedSignaturesEvent, getFailedExecution, @@ -281,13 +271,11 @@ describe('getFinalizationEvent', () => { await getFinalizationEvent( true, contract, - eventName, web3, setResult, - waitingBlocksResolved, message, - interval, - subscriptions, + subscriptions.push.bind(subscriptions), + isCancelled, timestamp, collectedSignaturesEvent, getFailedExecution, diff --git a/alm/src/utils/executionWaitingForBlocks.ts b/alm/src/utils/executionWaitingForBlocks.ts deleted file mode 100644 index a221f311..00000000 --- a/alm/src/utils/executionWaitingForBlocks.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { BlockNumberProvider } from '../services/BlockNumberProvider' -import { VALIDATOR_CONFIRMATION_STATUS } from '../config/constants' -import { EventData } from 'web3-eth-contract' - -export const checkWaitingBlocksForExecution = async ( - blockProvider: BlockNumberProvider, - interval: number, - targetBlock: number, - collectedSignaturesEvent: EventData, - setWaitingBlocksForExecution: Function, - setWaitingBlocksForExecutionResolved: Function, - setExecutionData: Function, - subscriptions: number[] -) => { - const currentBlock = blockProvider.get() - - if (currentBlock && currentBlock >= targetBlock) { - const undefinedExecutionState = { - status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED, - validator: collectedSignaturesEvent.returnValues.authorityResponsibleForRelay, - txHash: '', - timestamp: 0, - executionResult: false - } - setExecutionData( - (data: any) => - data.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || data.status === VALIDATOR_CONFIRMATION_STATUS.WAITING - ? undefinedExecutionState - : data - ) - setWaitingBlocksForExecutionResolved(true) - setWaitingBlocksForExecution(false) - } else { - let nextInterval = interval - if (!currentBlock) { - nextInterval = 500 - } else { - setWaitingBlocksForExecution(true) - const waitingExecutionState = { - status: VALIDATOR_CONFIRMATION_STATUS.WAITING, - validator: collectedSignaturesEvent.returnValues.authorityResponsibleForRelay, - txHash: '', - timestamp: 0, - executionResult: false - } - setExecutionData( - (data: any) => - data.status === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || - data.status === VALIDATOR_CONFIRMATION_STATUS.WAITING - ? waitingExecutionState - : data - ) - } - const timeoutId = setTimeout( - () => - checkWaitingBlocksForExecution( - blockProvider, - interval, - targetBlock, - collectedSignaturesEvent, - setWaitingBlocksForExecution, - setWaitingBlocksForExecutionResolved, - setExecutionData, - subscriptions - ), - nextInterval - ) - subscriptions.push(timeoutId) - } -} diff --git a/alm/src/utils/getCollectedSignaturesEvent.ts b/alm/src/utils/getCollectedSignaturesEvent.ts deleted file mode 100644 index 003a6095..00000000 --- a/alm/src/utils/getCollectedSignaturesEvent.ts +++ /dev/null @@ -1,52 +0,0 @@ -import Web3 from 'web3' -import { Contract, EventData } from 'web3-eth-contract' -import { homeBlockNumberProvider } from '../services/BlockNumberProvider' -import { BLOCK_RANGE } from '../config/constants' - -export const getCollectedSignaturesEvent = async ( - web3: Maybe, - contract: Maybe, - fromBlock: number, - toBlock: number, - messageHash: string, - setCollectedSignaturesEvent: Function, - subscriptions: number[] -) => { - if (!web3 || !contract) return - const currentBlock = homeBlockNumberProvider.get() - - let events: EventData[] = [] - let securedToBlock = toBlock - if (currentBlock) { - // prevent errors if the toBlock parameter is bigger than the latest - securedToBlock = toBlock >= currentBlock ? currentBlock : toBlock - events = await contract.getPastEvents('CollectedSignatures', { - fromBlock, - toBlock: securedToBlock - }) - } - - const filteredEvents = events.filter(e => e.returnValues.messageHash === messageHash) - - if (filteredEvents.length) { - const event = filteredEvents[0] - setCollectedSignaturesEvent(event) - } else { - const newFromBlock = currentBlock ? securedToBlock : fromBlock - const newToBlock = currentBlock ? toBlock + BLOCK_RANGE : toBlock - const timeoutId = setTimeout( - () => - getCollectedSignaturesEvent( - web3, - contract, - newFromBlock, - newToBlock, - messageHash, - setCollectedSignaturesEvent, - subscriptions - ), - 500 - ) - subscriptions.push(timeoutId) - } -} diff --git a/alm/src/utils/getConfirmationsForTx.ts b/alm/src/utils/getConfirmationsForTx.ts index 015793d0..54374efb 100644 --- a/alm/src/utils/getConfirmationsForTx.ts +++ b/alm/src/utils/getConfirmationsForTx.ts @@ -29,15 +29,15 @@ const mergeConfirmations = (oldConfirmations: BasicConfirmationParam[], newConfi export const getConfirmationsForTx = async ( messageData: string, - web3: Maybe, + web3: Web3, validatorList: string[], - bridgeContract: Maybe, + bridgeContract: Contract, fromHome: boolean, setResult: Function, requiredSignatures: number, setSignatureCollected: Function, - waitingBlocksResolved: boolean, - subscriptions: number[], + setTimeoutId: (timeoutId: number) => void, + isCancelled: () => boolean, startBlock: number, getFailedTransactions: (args: GetTransactionParams) => Promise, setFailedConfirmations: Function, @@ -45,8 +45,6 @@ export const getConfirmationsForTx = async ( setPendingConfirmations: Function, getSuccessTransactions: (args: GetTransactionParams) => Promise ) => { - if (!web3 || !validatorList || !validatorList.length || !bridgeContract || !waitingBlocksResolved) return - const confirmationContractMethod = fromHome ? getMessagesSigned : getAffirmationsSigned const hashMsg = web3.utils.soliditySha3Raw(messageData) @@ -144,28 +142,30 @@ export const getConfirmationsForTx = async ( (!hasEnoughSignatures && missingConfirmations.length > 0) || successConfirmationWithTxFound.length < successConfirmationWithData.length ) { - const timeoutId = setTimeout( - () => - getConfirmationsForTx( - messageData, - web3, - validatorList, - bridgeContract, - fromHome, - setResult, - requiredSignatures, - setSignatureCollected, - waitingBlocksResolved, - subscriptions, - startBlock, - getFailedTransactions, - setFailedConfirmations, - getPendingTransactions, - setPendingConfirmations, - getSuccessTransactions - ), - HOME_RPC_POLLING_INTERVAL - ) - subscriptions.push(timeoutId) + if (!isCancelled()) { + const timeoutId = setTimeout( + () => + getConfirmationsForTx( + messageData, + web3, + validatorList, + bridgeContract, + fromHome, + setResult, + requiredSignatures, + setSignatureCollected, + setTimeoutId, + isCancelled, + startBlock, + getFailedTransactions, + setFailedConfirmations, + getPendingTransactions, + setPendingConfirmations, + getSuccessTransactions + ), + HOME_RPC_POLLING_INTERVAL + ) + setTimeoutId(timeoutId) + } } } diff --git a/alm/src/utils/getFinalizationEvent.ts b/alm/src/utils/getFinalizationEvent.ts index 2ead8972..81c0a6d7 100644 --- a/alm/src/utils/getFinalizationEvent.ts +++ b/alm/src/utils/getFinalizationEvent.ts @@ -3,7 +3,9 @@ import Web3 from 'web3' import { CACHE_KEY_EXECUTION_FAILED, FOREIGN_EXPLORER_API, + FOREIGN_RPC_POLLING_INTERVAL, HOME_EXPLORER_API, + HOME_RPC_POLLING_INTERVAL, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants' import { ExecutionData } from '../hooks/useMessageConfirmations' @@ -69,14 +71,12 @@ export const getSuccessExecutionData = async ( export const getFinalizationEvent = async ( fromHome: boolean, - contract: Maybe, - eventName: string, - web3: Maybe, + contract: Contract, + web3: Web3, setResult: React.Dispatch>, - waitingBlocksResolved: boolean, message: MessageObject, - interval: number, - subscriptions: number[], + setTimeoutId: (timeoutId: number) => void, + isCancelled: () => boolean, startBlock: number, collectedSignaturesEvent: Maybe, getFailedExecution: (args: GetTransactionParams) => Promise, @@ -85,9 +85,11 @@ export const getFinalizationEvent = async ( setPendingExecution: Function, setExecutionEventsFetched: Function ) => { - if (!contract || !web3 || !waitingBlocksResolved) return + const eventName = fromHome ? 'RelayedMessage' : 'AffirmationCompleted' const api = fromHome ? FOREIGN_EXPLORER_API : HOME_EXPLORER_API + const successExecutionData = await getSuccessExecutionData(contract, eventName, web3, message.id, api) + if (successExecutionData) { setResult(successExecutionData) } else { @@ -150,28 +152,28 @@ export const getFinalizationEvent = async ( } } - const timeoutId = setTimeout( - () => - getFinalizationEvent( - fromHome, - contract, - eventName, - web3, - setResult, - waitingBlocksResolved, - message, - interval, - subscriptions, - startBlock, - collectedSignaturesEvent, - getFailedExecution, - setFailedExecution, - getPendingExecution, - setPendingExecution, - setExecutionEventsFetched - ), - interval - ) - subscriptions.push(timeoutId) + if (!isCancelled()) { + const timeoutId = setTimeout( + () => + getFinalizationEvent( + fromHome, + contract, + web3, + setResult, + message, + setTimeoutId, + isCancelled, + startBlock, + collectedSignaturesEvent, + getFailedExecution, + setFailedExecution, + getPendingExecution, + setPendingExecution, + setExecutionEventsFetched + ), + fromHome ? FOREIGN_RPC_POLLING_INTERVAL : HOME_RPC_POLLING_INTERVAL + ) + setTimeoutId(timeoutId) + } } } diff --git a/alm/src/utils/signatureWaitingForBlocks.ts b/alm/src/utils/signatureWaitingForBlocks.ts deleted file mode 100644 index 51db374d..00000000 --- a/alm/src/utils/signatureWaitingForBlocks.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { VALIDATOR_CONFIRMATION_STATUS } from '../config/constants' -import { BlockNumberProvider } from '../services/BlockNumberProvider' - -export const checkSignaturesWaitingForBLocks = async ( - targetBlock: number, - setWaitingStatus: Function, - setWaitingBlocksResolved: Function, - validatorList: string[], - setConfirmations: Function, - blockProvider: BlockNumberProvider, - interval: number, - subscriptions: number[] -) => { - const currentBlock = blockProvider.get() - - if (currentBlock && currentBlock >= targetBlock) { - setWaitingBlocksResolved(true) - setWaitingStatus(false) - } else { - let nextInterval = interval - if (!currentBlock) { - nextInterval = 500 - } else { - const validatorsWaiting = validatorList.map(validator => { - return { - validator, - status: VALIDATOR_CONFIRMATION_STATUS.WAITING - } - }) - setWaitingStatus(true) - setConfirmations(validatorsWaiting) - } - const timeoutId = setTimeout( - () => - checkSignaturesWaitingForBLocks( - targetBlock, - setWaitingStatus, - setWaitingBlocksResolved, - validatorList, - setConfirmations, - blockProvider, - interval, - subscriptions - ), - nextInterval - ) - subscriptions.push(timeoutId) - } -}