Improve performance of BS requests in ALM (#516)
This commit is contained in:
parent
626f9376b2
commit
9fd3f6ab82
@ -39,10 +39,17 @@ export interface ConfirmationsContainerParams {
|
|||||||
message: MessageObject
|
message: MessageObject
|
||||||
receipt: Maybe<TransactionReceipt>
|
receipt: Maybe<TransactionReceipt>
|
||||||
fromHome: boolean
|
fromHome: boolean
|
||||||
timestamp: number
|
homeStartBlock: Maybe<number>
|
||||||
|
foreignStartBlock: Maybe<number>
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ConfirmationsContainer = ({ message, receipt, fromHome, timestamp }: ConfirmationsContainerParams) => {
|
export const ConfirmationsContainer = ({
|
||||||
|
message,
|
||||||
|
receipt,
|
||||||
|
fromHome,
|
||||||
|
homeStartBlock,
|
||||||
|
foreignStartBlock
|
||||||
|
}: ConfirmationsContainerParams) => {
|
||||||
const {
|
const {
|
||||||
home: { name: homeName },
|
home: { name: homeName },
|
||||||
foreign: { name: foreignName }
|
foreign: { name: foreignName }
|
||||||
@ -62,7 +69,8 @@ export const ConfirmationsContainer = ({ message, receipt, fromHome, timestamp }
|
|||||||
message,
|
message,
|
||||||
receipt,
|
receipt,
|
||||||
fromHome,
|
fromHome,
|
||||||
timestamp,
|
homeStartBlock,
|
||||||
|
foreignStartBlock,
|
||||||
requiredSignatures,
|
requiredSignatures,
|
||||||
validatorList,
|
validatorList,
|
||||||
blockConfirmations
|
blockConfirmations
|
||||||
|
@ -10,6 +10,7 @@ import { ExplorerTxLink } from './commons/ExplorerTxLink'
|
|||||||
import { ConfirmationsContainer } from './ConfirmationsContainer'
|
import { ConfirmationsContainer } from './ConfirmationsContainer'
|
||||||
import { TransactionReceipt } from 'web3-eth'
|
import { TransactionReceipt } from 'web3-eth'
|
||||||
import { BackButton } from './commons/BackButton'
|
import { BackButton } from './commons/BackButton'
|
||||||
|
import { useClosestBlock } from '../hooks/useClosestBlock'
|
||||||
|
|
||||||
export interface StatusContainerParam {
|
export interface StatusContainerParam {
|
||||||
onBackToMain: () => void
|
onBackToMain: () => void
|
||||||
@ -23,12 +24,15 @@ export const StatusContainer = ({ onBackToMain, setNetworkFromParams, receiptPar
|
|||||||
const { chainId, txHash, messageIdParam } = useParams()
|
const { chainId, txHash, messageIdParam } = useParams()
|
||||||
const validChainId = chainId === home.chainId.toString() || chainId === foreign.chainId.toString()
|
const validChainId = chainId === home.chainId.toString() || chainId === foreign.chainId.toString()
|
||||||
const validParameters = validChainId && validTxHash(txHash)
|
const validParameters = validChainId && validTxHash(txHash)
|
||||||
|
const isHome = chainId === home.chainId.toString()
|
||||||
|
|
||||||
const { messages, receipt, status, description, timestamp, loading } = useTransactionStatus({
|
const { messages, receipt, status, description, timestamp, loading } = useTransactionStatus({
|
||||||
txHash: validParameters ? txHash : '',
|
txHash: validParameters ? txHash : '',
|
||||||
chainId: validParameters ? parseInt(chainId) : 0,
|
chainId: validParameters ? parseInt(chainId) : 0,
|
||||||
receiptParam
|
receiptParam
|
||||||
})
|
})
|
||||||
|
const homeStartBlock = useClosestBlock(true, isHome, receipt, timestamp)
|
||||||
|
const foreignStartBlock = useClosestBlock(false, isHome, receipt, timestamp)
|
||||||
|
|
||||||
const selectedMessageId = messageIdParam === undefined || messages[messageIdParam] === undefined ? -1 : messageIdParam
|
const selectedMessageId = messageIdParam === undefined || messages[messageIdParam] === undefined ? -1 : messageIdParam
|
||||||
|
|
||||||
@ -64,7 +68,6 @@ export const StatusContainer = ({ onBackToMain, setNetworkFromParams, receiptPar
|
|||||||
const displayReference = multiMessageSelected ? messages[selectedMessageId].id : txHash
|
const displayReference = multiMessageSelected ? messages[selectedMessageId].id : txHash
|
||||||
const formattedMessageId = formatTxHash(displayReference)
|
const formattedMessageId = formatTxHash(displayReference)
|
||||||
|
|
||||||
const isHome = chainId === home.chainId.toString()
|
|
||||||
const txExplorerLink = getExplorerTxUrl(txHash, isHome)
|
const txExplorerLink = getExplorerTxUrl(txHash, isHome)
|
||||||
const displayExplorerLink = status !== TRANSACTION_STATUS.NOT_FOUND
|
const displayExplorerLink = status !== TRANSACTION_STATUS.NOT_FOUND
|
||||||
|
|
||||||
@ -101,7 +104,13 @@ export const StatusContainer = ({ onBackToMain, setNetworkFromParams, receiptPar
|
|||||||
)}
|
)}
|
||||||
{displayMessageSelector && <MessageSelector messages={messages} onMessageSelected={onMessageSelected} />}
|
{displayMessageSelector && <MessageSelector messages={messages} onMessageSelected={onMessageSelected} />}
|
||||||
{displayConfirmations && (
|
{displayConfirmations && (
|
||||||
<ConfirmationsContainer message={messageToConfirm} receipt={receipt} fromHome={isHome} timestamp={timestamp} />
|
<ConfirmationsContainer
|
||||||
|
message={messageToConfirm}
|
||||||
|
receipt={receipt}
|
||||||
|
fromHome={isHome}
|
||||||
|
homeStartBlock={homeStartBlock}
|
||||||
|
foreignStartBlock={foreignStartBlock}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<BackButton onBackToMain={onBackToMain} />
|
<BackButton onBackToMain={onBackToMain} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -18,9 +18,8 @@ export const ALM_HOME_TO_FOREIGN_MANUAL_EXECUTION: boolean =
|
|||||||
|
|
||||||
export const HOME_RPC_POLLING_INTERVAL: number = 5000
|
export const HOME_RPC_POLLING_INTERVAL: number = 5000
|
||||||
export const FOREIGN_RPC_POLLING_INTERVAL: number = 5000
|
export const FOREIGN_RPC_POLLING_INTERVAL: number = 5000
|
||||||
export const BLOCK_RANGE: number = 50
|
export const BLOCK_RANGE: number = 500
|
||||||
export const ONE_DAY_TIMESTAMP: number = 86400
|
export const MAX_TX_SEARCH_BLOCK_RANGE: number = 10000
|
||||||
export const THREE_DAYS_TIMESTAMP: number = 259200
|
|
||||||
|
|
||||||
export const EXECUTE_AFFIRMATION_HASH = 'e7a2c01f'
|
export const EXECUTE_AFFIRMATION_HASH = 'e7a2c01f'
|
||||||
export const SUBMIT_SIGNATURE_HASH = '630cea8e'
|
export const SUBMIT_SIGNATURE_HASH = '630cea8e'
|
||||||
|
68
alm/src/hooks/useClosestBlock.ts
Normal file
68
alm/src/hooks/useClosestBlock.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import { useEffect, useState } from 'react'
|
||||||
|
import { TransactionReceipt } from 'web3-eth'
|
||||||
|
import { useStateProvider } from '../state/StateProvider'
|
||||||
|
import { FOREIGN_EXPLORER_API, HOME_EXPLORER_API } from '../config/constants'
|
||||||
|
import { getClosestBlockByTimestamp } from '../utils/explorer'
|
||||||
|
|
||||||
|
export function useClosestBlock(
|
||||||
|
searchHome: boolean,
|
||||||
|
fromHome: boolean,
|
||||||
|
receipt: Maybe<TransactionReceipt>,
|
||||||
|
timestamp: number
|
||||||
|
) {
|
||||||
|
const { home, foreign } = useStateProvider()
|
||||||
|
const [blockNumber, setBlockNumber] = useState<number | null>(null)
|
||||||
|
|
||||||
|
useEffect(
|
||||||
|
() => {
|
||||||
|
if (!receipt || blockNumber || !timestamp) return
|
||||||
|
|
||||||
|
if (fromHome === searchHome) {
|
||||||
|
setBlockNumber(receipt.blockNumber)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const web3 = searchHome ? home.web3 : foreign.web3
|
||||||
|
if (!web3) return
|
||||||
|
|
||||||
|
const getBlock = async () => {
|
||||||
|
// try to fast-fetch closest block number from the chain explorer
|
||||||
|
try {
|
||||||
|
const api = searchHome ? HOME_EXPLORER_API : FOREIGN_EXPLORER_API
|
||||||
|
setBlockNumber(await getClosestBlockByTimestamp(api, timestamp))
|
||||||
|
return
|
||||||
|
} catch {}
|
||||||
|
|
||||||
|
const lastBlock = await web3.eth.getBlock('latest')
|
||||||
|
if (lastBlock.timestamp <= timestamp) {
|
||||||
|
setBlockNumber(lastBlock.number)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const oldBlock = await web3.eth.getBlock(Math.max(lastBlock.number - 10000, 1))
|
||||||
|
const blockDiff = lastBlock.number - oldBlock.number
|
||||||
|
const timeDiff = (lastBlock.timestamp as number) - (oldBlock.timestamp as number)
|
||||||
|
const averageBlockTime = timeDiff / blockDiff
|
||||||
|
let currentBlock = lastBlock
|
||||||
|
|
||||||
|
let prevBlockDiff = Infinity
|
||||||
|
while (true) {
|
||||||
|
const timeDiff = (currentBlock.timestamp as number) - timestamp
|
||||||
|
const blockDiff = Math.ceil(timeDiff / averageBlockTime)
|
||||||
|
if (Math.abs(blockDiff) < 5 || Math.abs(blockDiff) >= Math.abs(prevBlockDiff)) {
|
||||||
|
setBlockNumber(currentBlock.number - blockDiff - 5)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
prevBlockDiff = blockDiff
|
||||||
|
currentBlock = await web3.eth.getBlock(currentBlock.number - blockDiff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getBlock()
|
||||||
|
},
|
||||||
|
[blockNumber, foreign.web3, fromHome, home.web3, receipt, searchHome, timestamp]
|
||||||
|
)
|
||||||
|
|
||||||
|
return blockNumber
|
||||||
|
}
|
@ -28,7 +28,8 @@ export interface useMessageConfirmationsParams {
|
|||||||
message: MessageObject
|
message: MessageObject
|
||||||
receipt: Maybe<TransactionReceipt>
|
receipt: Maybe<TransactionReceipt>
|
||||||
fromHome: boolean
|
fromHome: boolean
|
||||||
timestamp: number
|
homeStartBlock: Maybe<number>
|
||||||
|
foreignStartBlock: Maybe<number>
|
||||||
requiredSignatures: number
|
requiredSignatures: number
|
||||||
validatorList: string[]
|
validatorList: string[]
|
||||||
blockConfirmations: number
|
blockConfirmations: number
|
||||||
@ -56,7 +57,8 @@ export const useMessageConfirmations = ({
|
|||||||
message,
|
message,
|
||||||
receipt,
|
receipt,
|
||||||
fromHome,
|
fromHome,
|
||||||
timestamp,
|
homeStartBlock,
|
||||||
|
foreignStartBlock,
|
||||||
requiredSignatures,
|
requiredSignatures,
|
||||||
validatorList,
|
validatorList,
|
||||||
blockConfirmations
|
blockConfirmations
|
||||||
@ -90,6 +92,17 @@ export const useMessageConfirmations = ({
|
|||||||
return filteredList.length > 0
|
return filteredList.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start watching blocks at the start
|
||||||
|
useEffect(
|
||||||
|
() => {
|
||||||
|
if (!home.web3 || !foreign.web3) return
|
||||||
|
|
||||||
|
homeBlockNumberProvider.start(home.web3)
|
||||||
|
foreignBlockNumberProvider.start(foreign.web3)
|
||||||
|
},
|
||||||
|
[foreign.web3, home.web3]
|
||||||
|
)
|
||||||
|
|
||||||
// Check if the validators are waiting for block confirmations to verify the message
|
// Check if the validators are waiting for block confirmations to verify the message
|
||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
@ -105,9 +118,6 @@ export const useMessageConfirmations = ({
|
|||||||
|
|
||||||
const blockProvider = fromHome ? homeBlockNumberProvider : foreignBlockNumberProvider
|
const blockProvider = fromHome ? homeBlockNumberProvider : foreignBlockNumberProvider
|
||||||
const interval = fromHome ? HOME_RPC_POLLING_INTERVAL : FOREIGN_RPC_POLLING_INTERVAL
|
const interval = fromHome ? HOME_RPC_POLLING_INTERVAL : FOREIGN_RPC_POLLING_INTERVAL
|
||||||
const web3 = fromHome ? home.web3 : foreign.web3
|
|
||||||
blockProvider.start(web3)
|
|
||||||
|
|
||||||
const targetBlock = receipt.blockNumber + blockConfirmations
|
const targetBlock = receipt.blockNumber + blockConfirmations
|
||||||
|
|
||||||
checkSignaturesWaitingForBLocks(
|
checkSignaturesWaitingForBLocks(
|
||||||
@ -123,7 +133,6 @@ export const useMessageConfirmations = ({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
blockProvider.stop()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
@ -153,8 +162,6 @@ export const useMessageConfirmations = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
homeBlockNumberProvider.start(home.web3)
|
|
||||||
|
|
||||||
const fromBlock = receipt.blockNumber
|
const fromBlock = receipt.blockNumber
|
||||||
const toBlock = fromBlock + BLOCK_RANGE
|
const toBlock = fromBlock + BLOCK_RANGE
|
||||||
const messageHash = home.web3.utils.soliditySha3Raw(message.data)
|
const messageHash = home.web3.utils.soliditySha3Raw(message.data)
|
||||||
@ -171,7 +178,6 @@ export const useMessageConfirmations = ({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
homeBlockNumberProvider.stop()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[fromHome, home.bridgeContract, home.web3, message.data, receipt, signatureCollected]
|
[fromHome, home.bridgeContract, home.web3, message.data, receipt, signatureCollected]
|
||||||
@ -192,7 +198,6 @@ export const useMessageConfirmations = ({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
homeBlockNumberProvider.start(home.web3)
|
|
||||||
const targetBlock = collectedSignaturesEvent.blockNumber + blockConfirmations
|
const targetBlock = collectedSignaturesEvent.blockNumber + blockConfirmations
|
||||||
|
|
||||||
checkWaitingBlocksForExecution(
|
checkWaitingBlocksForExecution(
|
||||||
@ -208,7 +213,6 @@ export const useMessageConfirmations = ({
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
homeBlockNumberProvider.stop()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[collectedSignaturesEvent, fromHome, blockConfirmations, home.web3, receipt, waitingBlocksForExecutionResolved]
|
[collectedSignaturesEvent, fromHome, blockConfirmations, home.web3, receipt, waitingBlocksForExecutionResolved]
|
||||||
@ -218,7 +222,7 @@ export const useMessageConfirmations = ({
|
|||||||
// To avoid making extra requests, this is only executed when validators finished waiting for blocks confirmations
|
// To avoid making extra requests, this is only executed when validators finished waiting for blocks confirmations
|
||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
if (!waitingBlocksResolved || !timestamp || !requiredSignatures) return
|
if (!waitingBlocksResolved || !homeStartBlock || !requiredSignatures) return
|
||||||
|
|
||||||
const subscriptions: Array<number> = []
|
const subscriptions: Array<number> = []
|
||||||
|
|
||||||
@ -239,7 +243,7 @@ export const useMessageConfirmations = ({
|
|||||||
setSignatureCollected,
|
setSignatureCollected,
|
||||||
waitingBlocksResolved,
|
waitingBlocksResolved,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
timestamp,
|
homeStartBlock,
|
||||||
getValidatorFailedTransactionsForMessage,
|
getValidatorFailedTransactionsForMessage,
|
||||||
setFailedConfirmations,
|
setFailedConfirmations,
|
||||||
getValidatorPendingTransactionsForMessage,
|
getValidatorPendingTransactionsForMessage,
|
||||||
@ -259,7 +263,7 @@ export const useMessageConfirmations = ({
|
|||||||
home.bridgeContract,
|
home.bridgeContract,
|
||||||
requiredSignatures,
|
requiredSignatures,
|
||||||
waitingBlocksResolved,
|
waitingBlocksResolved,
|
||||||
timestamp,
|
homeStartBlock,
|
||||||
setConfirmations
|
setConfirmations
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
@ -270,6 +274,8 @@ export const useMessageConfirmations = ({
|
|||||||
useEffect(
|
useEffect(
|
||||||
() => {
|
() => {
|
||||||
if ((fromHome && !waitingBlocksForExecutionResolved) || (!fromHome && !waitingBlocksResolved)) return
|
if ((fromHome && !waitingBlocksForExecutionResolved) || (!fromHome && !waitingBlocksResolved)) return
|
||||||
|
const startBlock = fromHome ? foreignStartBlock : homeStartBlock
|
||||||
|
if (!startBlock) return
|
||||||
|
|
||||||
const subscriptions: Array<number> = []
|
const subscriptions: Array<number> = []
|
||||||
|
|
||||||
@ -285,6 +291,7 @@ export const useMessageConfirmations = ({
|
|||||||
const interval = fromHome ? FOREIGN_RPC_POLLING_INTERVAL : HOME_RPC_POLLING_INTERVAL
|
const interval = fromHome ? FOREIGN_RPC_POLLING_INTERVAL : HOME_RPC_POLLING_INTERVAL
|
||||||
|
|
||||||
getFinalizationEvent(
|
getFinalizationEvent(
|
||||||
|
fromHome,
|
||||||
bridgeContract,
|
bridgeContract,
|
||||||
contractEvent,
|
contractEvent,
|
||||||
providedWeb3,
|
providedWeb3,
|
||||||
@ -293,7 +300,7 @@ export const useMessageConfirmations = ({
|
|||||||
message,
|
message,
|
||||||
interval,
|
interval,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
timestamp,
|
startBlock,
|
||||||
collectedSignaturesEvent,
|
collectedSignaturesEvent,
|
||||||
getExecutionFailedTransactionForMessage,
|
getExecutionFailedTransactionForMessage,
|
||||||
setFailedExecution,
|
setFailedExecution,
|
||||||
@ -315,8 +322,9 @@ export const useMessageConfirmations = ({
|
|||||||
home.web3,
|
home.web3,
|
||||||
waitingBlocksResolved,
|
waitingBlocksResolved,
|
||||||
waitingBlocksForExecutionResolved,
|
waitingBlocksForExecutionResolved,
|
||||||
timestamp,
|
collectedSignaturesEvent,
|
||||||
collectedSignaturesEvent
|
foreignStartBlock,
|
||||||
|
homeStartBlock
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -328,6 +336,9 @@ export const useMessageConfirmations = ({
|
|||||||
? CONFIRMATIONS_STATUS.SUCCESS
|
? CONFIRMATIONS_STATUS.SUCCESS
|
||||||
: CONFIRMATIONS_STATUS.SUCCESS_MESSAGE_FAILED
|
: CONFIRMATIONS_STATUS.SUCCESS_MESSAGE_FAILED
|
||||||
setStatus(newStatus)
|
setStatus(newStatus)
|
||||||
|
|
||||||
|
foreignBlockNumberProvider.stop()
|
||||||
|
homeBlockNumberProvider.stop()
|
||||||
} else if (signatureCollected) {
|
} else if (signatureCollected) {
|
||||||
if (fromHome) {
|
if (fromHome) {
|
||||||
if (waitingBlocksForExecution) {
|
if (waitingBlocksForExecution) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
import differenceInMilliseconds from 'date-fns/differenceInMilliseconds'
|
import differenceInMilliseconds from 'date-fns/differenceInMilliseconds'
|
||||||
import { HOME_RPC_POLLING_INTERVAL } from '../config/constants'
|
import { FOREIGN_RPC_POLLING_INTERVAL, HOME_RPC_POLLING_INTERVAL } from '../config/constants'
|
||||||
|
|
||||||
export class BlockNumberProvider {
|
export class BlockNumberProvider {
|
||||||
private running: number
|
private running: number
|
||||||
@ -61,4 +61,4 @@ export class BlockNumberProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const homeBlockNumberProvider = new BlockNumberProvider(HOME_RPC_POLLING_INTERVAL)
|
export const homeBlockNumberProvider = new BlockNumberProvider(HOME_RPC_POLLING_INTERVAL)
|
||||||
export const foreignBlockNumberProvider = new BlockNumberProvider(HOME_RPC_POLLING_INTERVAL)
|
export const foreignBlockNumberProvider = new BlockNumberProvider(FOREIGN_RPC_POLLING_INTERVAL)
|
||||||
|
@ -17,19 +17,33 @@ const otherAddress = '0xD4075FB57fCf038bFc702c915Ef9592534bED5c1'
|
|||||||
|
|
||||||
describe('getFailedTransactions', () => {
|
describe('getFailedTransactions', () => {
|
||||||
test('should only return failed transactions', async () => {
|
test('should only return failed transactions', async () => {
|
||||||
const transactions = [{ isError: '0' }, { isError: '1' }, { isError: '0' }, { isError: '1' }, { isError: '1' }]
|
const to = otherAddress
|
||||||
|
const transactions = [
|
||||||
|
{ isError: '0', to },
|
||||||
|
{ isError: '1', to },
|
||||||
|
{ isError: '0', to },
|
||||||
|
{ isError: '1', to },
|
||||||
|
{ isError: '1', to }
|
||||||
|
]
|
||||||
|
|
||||||
const fetchAccountTransactions = jest.fn().mockImplementation(() => transactions)
|
const fetchAccountTransactions = jest.fn().mockImplementation(() => transactions)
|
||||||
const result = await getFailedTransactions('', '', 0, 1, '', fetchAccountTransactions)
|
const result = await getFailedTransactions('', to, 0, 1, '', fetchAccountTransactions)
|
||||||
expect(result.length).toEqual(3)
|
expect(result.length).toEqual(3)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
describe('getSuccessTransactions', () => {
|
describe('getSuccessTransactions', () => {
|
||||||
test('should only return success transactions', async () => {
|
test('should only return success transactions', async () => {
|
||||||
const transactions = [{ isError: '0' }, { isError: '1' }, { isError: '0' }, { isError: '1' }, { isError: '1' }]
|
const to = otherAddress
|
||||||
|
const transactions = [
|
||||||
|
{ isError: '0', to },
|
||||||
|
{ isError: '1', to },
|
||||||
|
{ isError: '0', to },
|
||||||
|
{ isError: '1', to },
|
||||||
|
{ isError: '1', to }
|
||||||
|
]
|
||||||
|
|
||||||
const fetchAccountTransactions = jest.fn().mockImplementation(() => transactions)
|
const fetchAccountTransactions = jest.fn().mockImplementation(() => transactions)
|
||||||
const result = await getSuccessTransactions('', '', 0, 1, '', fetchAccountTransactions)
|
const result = await getSuccessTransactions('', to, 0, 1, '', fetchAccountTransactions)
|
||||||
expect(result.length).toEqual(2)
|
expect(result.length).toEqual(2)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -74,8 +88,8 @@ describe('getExecutionFailedTransactionForMessage', () => {
|
|||||||
account: '',
|
account: '',
|
||||||
to: '',
|
to: '',
|
||||||
messageData,
|
messageData,
|
||||||
startTimestamp: 0,
|
startBlock: 0,
|
||||||
endTimestamp: 1
|
endBlock: 1
|
||||||
},
|
},
|
||||||
fetchAccountTransactions
|
fetchAccountTransactions
|
||||||
)
|
)
|
||||||
|
@ -64,6 +64,7 @@ describe('getFinalizationEvent', () => {
|
|||||||
const setExecutionEventsFetched = jest.fn()
|
const setExecutionEventsFetched = jest.fn()
|
||||||
|
|
||||||
await getFinalizationEvent(
|
await getFinalizationEvent(
|
||||||
|
true,
|
||||||
contract,
|
contract,
|
||||||
eventName,
|
eventName,
|
||||||
web3,
|
web3,
|
||||||
@ -115,6 +116,7 @@ describe('getFinalizationEvent', () => {
|
|||||||
const setExecutionEventsFetched = jest.fn()
|
const setExecutionEventsFetched = jest.fn()
|
||||||
|
|
||||||
await getFinalizationEvent(
|
await getFinalizationEvent(
|
||||||
|
true,
|
||||||
contract,
|
contract,
|
||||||
eventName,
|
eventName,
|
||||||
web3,
|
web3,
|
||||||
@ -166,6 +168,7 @@ describe('getFinalizationEvent', () => {
|
|||||||
const setExecutionEventsFetched = jest.fn()
|
const setExecutionEventsFetched = jest.fn()
|
||||||
|
|
||||||
await getFinalizationEvent(
|
await getFinalizationEvent(
|
||||||
|
true,
|
||||||
contract,
|
contract,
|
||||||
eventName,
|
eventName,
|
||||||
web3,
|
web3,
|
||||||
@ -217,6 +220,7 @@ describe('getFinalizationEvent', () => {
|
|||||||
const setExecutionEventsFetched = jest.fn()
|
const setExecutionEventsFetched = jest.fn()
|
||||||
|
|
||||||
await getFinalizationEvent(
|
await getFinalizationEvent(
|
||||||
|
true,
|
||||||
contract,
|
contract,
|
||||||
eventName,
|
eventName,
|
||||||
web3,
|
web3,
|
||||||
@ -275,6 +279,7 @@ describe('getFinalizationEvent', () => {
|
|||||||
const setExecutionEventsFetched = jest.fn()
|
const setExecutionEventsFetched = jest.fn()
|
||||||
|
|
||||||
await getFinalizationEvent(
|
await getFinalizationEvent(
|
||||||
|
true,
|
||||||
contract,
|
contract,
|
||||||
eventName,
|
eventName,
|
||||||
web3,
|
web3,
|
||||||
|
@ -30,7 +30,6 @@ export const checkWaitingBlocksForExecution = async (
|
|||||||
)
|
)
|
||||||
setWaitingBlocksForExecutionResolved(true)
|
setWaitingBlocksForExecutionResolved(true)
|
||||||
setWaitingBlocksForExecution(false)
|
setWaitingBlocksForExecution(false)
|
||||||
blockProvider.stop()
|
|
||||||
} else {
|
} else {
|
||||||
let nextInterval = interval
|
let nextInterval = interval
|
||||||
if (!currentBlock) {
|
if (!currentBlock) {
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
|
BLOCK_RANGE,
|
||||||
EXECUTE_AFFIRMATION_HASH,
|
EXECUTE_AFFIRMATION_HASH,
|
||||||
EXECUTE_SIGNATURES_HASH,
|
EXECUTE_SIGNATURES_HASH,
|
||||||
FOREIGN_EXPLORER_API,
|
FOREIGN_EXPLORER_API,
|
||||||
HOME_EXPLORER_API,
|
HOME_EXPLORER_API,
|
||||||
|
MAX_TX_SEARCH_BLOCK_RANGE,
|
||||||
SUBMIT_SIGNATURE_HASH
|
SUBMIT_SIGNATURE_HASH
|
||||||
} from '../config/constants'
|
} from '../config/constants'
|
||||||
|
|
||||||
@ -12,6 +14,7 @@ export interface APITransaction {
|
|||||||
input: string
|
input: string
|
||||||
to: string
|
to: string
|
||||||
hash: string
|
hash: string
|
||||||
|
blockNumber: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface APIPendingTransaction {
|
export interface APIPendingTransaction {
|
||||||
@ -27,106 +30,42 @@ export interface PendingTransactionsParams {
|
|||||||
|
|
||||||
export interface AccountTransactionsParams {
|
export interface AccountTransactionsParams {
|
||||||
account: string
|
account: string
|
||||||
to: string
|
startBlock: number
|
||||||
startTimestamp: number
|
endBlock: number
|
||||||
endTimestamp: number
|
|
||||||
api: string
|
api: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetFailedTransactionParams {
|
|
||||||
account: string
|
|
||||||
to: string
|
|
||||||
messageData: string
|
|
||||||
startTimestamp: number
|
|
||||||
endTimestamp: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GetPendingTransactionParams {
|
export interface GetPendingTransactionParams {
|
||||||
account: string
|
account: string
|
||||||
to: string
|
to: string
|
||||||
messageData: string
|
messageData: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchAccountTransactionsFromBlockscout = async ({
|
export interface GetTransactionParams extends GetPendingTransactionParams {
|
||||||
account,
|
startBlock: number
|
||||||
to,
|
endBlock: number
|
||||||
startTimestamp,
|
|
||||||
endTimestamp,
|
|
||||||
api
|
|
||||||
}: AccountTransactionsParams): Promise<APITransaction[]> => {
|
|
||||||
const url = `${api}?module=account&action=txlist&address=${account}&filterby=from=${account}&to=${to}&starttimestamp=${startTimestamp}&endtimestamp=${endTimestamp}`
|
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await fetch(url).then(res => res.json())
|
|
||||||
if (result.status === '0') {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.result
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getBlockByTimestampUrl = (api: string, timestamp: number) =>
|
export const fetchAccountTransactions = async ({ account, startBlock, endBlock, api }: AccountTransactionsParams) => {
|
||||||
`${api}&module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`
|
const params = `module=account&action=txlist&address=${account}&filterby=from&startblock=${startBlock}&endblock=${endBlock}`
|
||||||
|
const url = api.includes('blockscout') ? `${api}?${params}` : `${api}&${params}`
|
||||||
|
|
||||||
export const fetchAccountTransactionsFromEtherscan = async ({
|
const result = await fetch(url).then(res => res.json())
|
||||||
account,
|
|
||||||
to,
|
|
||||||
startTimestamp,
|
|
||||||
endTimestamp,
|
|
||||||
api
|
|
||||||
}: AccountTransactionsParams): Promise<APITransaction[]> => {
|
|
||||||
const startBlockUrl = getBlockByTimestampUrl(api, startTimestamp)
|
|
||||||
const endBlockUrl = getBlockByTimestampUrl(api, endTimestamp)
|
|
||||||
let fromBlock = 0
|
|
||||||
let toBlock = 9999999999999
|
|
||||||
try {
|
|
||||||
const [fromBlockResult, toBlockResult] = await Promise.all([
|
|
||||||
fetch(startBlockUrl).then(res => res.json()),
|
|
||||||
fetch(endBlockUrl).then(res => res.json())
|
|
||||||
])
|
|
||||||
|
|
||||||
if (fromBlockResult.status !== '0') {
|
if (result.message === 'No transactions found') {
|
||||||
fromBlock = parseInt(fromBlockResult.result)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toBlockResult.status !== '0') {
|
|
||||||
toBlock = parseInt(toBlockResult.result)
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
const url = `${api}&module=account&action=txlist&address=${account}&startblock=${fromBlock}&endblock=${toBlock}`
|
return result.result
|
||||||
|
|
||||||
try {
|
|
||||||
const result = await fetch(url).then(res => res.json())
|
|
||||||
|
|
||||||
if (result.status === '0') {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
|
|
||||||
const toAddressLowerCase = to.toLowerCase()
|
|
||||||
const transactions: APITransaction[] = result.result
|
|
||||||
return transactions.filter(t => t.to.toLowerCase() === toAddressLowerCase)
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const fetchAccountTransactions = (api: string) => {
|
|
||||||
return api.includes('blockscout') ? fetchAccountTransactionsFromBlockscout : fetchAccountTransactionsFromEtherscan
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const fetchPendingTransactions = async ({
|
export const fetchPendingTransactions = async ({
|
||||||
account,
|
account,
|
||||||
api
|
api
|
||||||
}: PendingTransactionsParams): Promise<APIPendingTransaction[]> => {
|
}: PendingTransactionsParams): Promise<APIPendingTransaction[]> => {
|
||||||
|
if (!api.includes('blockscout')) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
const url = `${api}?module=account&action=pendingtxlist&address=${account}`
|
const url = `${api}?module=account&action=pendingtxlist&address=${account}`
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -141,30 +80,96 @@ export const fetchPendingTransactions = async ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getClosestBlockByTimestamp = async (api: string, timestamp: number): Promise<number> => {
|
||||||
|
if (api.includes('blockscout')) {
|
||||||
|
throw new Error('Blockscout does not support getblocknobytime')
|
||||||
|
}
|
||||||
|
|
||||||
|
const url = `${api}&module=block&action=getblocknobytime×tamp=${timestamp}&closest=before`
|
||||||
|
|
||||||
|
const blockNumber = await fetch(url).then(res => res.json())
|
||||||
|
|
||||||
|
return parseInt(blockNumber.result)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fast version of fetchAccountTransactions
|
||||||
|
// sequentially fetches transactions in small batches
|
||||||
|
// caches the result
|
||||||
|
const transactionsCache: { [key: string]: { lastBlock: number; transactions: APITransaction[] } } = {}
|
||||||
|
export const getAccountTransactions = async ({
|
||||||
|
account,
|
||||||
|
startBlock,
|
||||||
|
endBlock,
|
||||||
|
api
|
||||||
|
}: AccountTransactionsParams): Promise<APITransaction[]> => {
|
||||||
|
const key = `${account}-${startBlock}-${api}`
|
||||||
|
|
||||||
|
// initialize empty cache if it doesn't exist yet
|
||||||
|
if (!transactionsCache[key]) {
|
||||||
|
transactionsCache[key] = { lastBlock: startBlock - 1, transactions: [] }
|
||||||
|
}
|
||||||
|
|
||||||
|
// if cache contains events up to block X,
|
||||||
|
// new batch is fetched for range [X + 1, X + 1 + BLOCK_RANGE]
|
||||||
|
const newStartBlock = transactionsCache[key].lastBlock + 1
|
||||||
|
const newEndBlock = newStartBlock + BLOCK_RANGE
|
||||||
|
|
||||||
|
// search for new transactions only if max allowed block range is not yet exceeded
|
||||||
|
if (newEndBlock <= startBlock + MAX_TX_SEARCH_BLOCK_RANGE) {
|
||||||
|
const newTransactions = await fetchAccountTransactions({
|
||||||
|
account,
|
||||||
|
startBlock: newStartBlock,
|
||||||
|
endBlock: newEndBlock,
|
||||||
|
api
|
||||||
|
})
|
||||||
|
|
||||||
|
const transactions = transactionsCache[key].transactions.concat(...newTransactions)
|
||||||
|
|
||||||
|
// cache updated transactions list
|
||||||
|
transactionsCache[key].transactions = transactions
|
||||||
|
|
||||||
|
// enbBlock is assumed to be the current block number of the chain
|
||||||
|
// if the whole range is finalized, last block can be safely updated to the end of the range
|
||||||
|
// this works even if there are no transactions in the list
|
||||||
|
if (newEndBlock < endBlock) {
|
||||||
|
transactionsCache[key].lastBlock = newEndBlock
|
||||||
|
} else if (transactions.length > 0) {
|
||||||
|
transactionsCache[key].lastBlock = parseInt(transactions[transactions.length - 1].blockNumber, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
return transactions
|
||||||
|
}
|
||||||
|
|
||||||
|
console.warn(`Reached max transaction searching range, returning previously cached transactions for ${account}`)
|
||||||
|
return transactionsCache[key].transactions
|
||||||
|
}
|
||||||
|
|
||||||
|
const filterReceiver = (to: string) => (tx: APITransaction) => tx.to.toLowerCase() === to.toLowerCase()
|
||||||
|
|
||||||
export const getFailedTransactions = async (
|
export const getFailedTransactions = async (
|
||||||
account: string,
|
account: string,
|
||||||
to: string,
|
to: string,
|
||||||
startTimestamp: number,
|
startBlock: number,
|
||||||
endTimestamp: number,
|
endBlock: number,
|
||||||
api: string,
|
api: string,
|
||||||
fetchAccountTransactions: (args: AccountTransactionsParams) => Promise<APITransaction[]>
|
getAccountTransactionsMethod = getAccountTransactions
|
||||||
): Promise<APITransaction[]> => {
|
): Promise<APITransaction[]> => {
|
||||||
const transactions = await fetchAccountTransactions({ account, to, startTimestamp, endTimestamp, api })
|
const transactions = await getAccountTransactionsMethod({ account, startBlock, endBlock, api })
|
||||||
|
|
||||||
return transactions.filter(t => t.isError !== '0')
|
return transactions.filter(t => t.isError !== '0').filter(filterReceiver(to))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getSuccessTransactions = async (
|
export const getSuccessTransactions = async (
|
||||||
account: string,
|
account: string,
|
||||||
to: string,
|
to: string,
|
||||||
startTimestamp: number,
|
startBlock: number,
|
||||||
endTimestamp: number,
|
endBlock: number,
|
||||||
api: string,
|
api: string,
|
||||||
fetchAccountTransactions: (args: AccountTransactionsParams) => Promise<APITransaction[]>
|
getAccountTransactionsMethod = getAccountTransactions
|
||||||
): Promise<APITransaction[]> => {
|
): Promise<APITransaction[]> => {
|
||||||
const transactions = await fetchAccountTransactions({ account, to, startTimestamp, endTimestamp, api })
|
const transactions = await getAccountTransactionsMethod({ account, startBlock, endBlock, api })
|
||||||
|
|
||||||
return transactions.filter(t => t.isError === '0')
|
return transactions.filter(t => t.isError === '0').filter(filterReceiver(to))
|
||||||
}
|
}
|
||||||
|
|
||||||
export const filterValidatorSignatureTransaction = (
|
export const filterValidatorSignatureTransaction = (
|
||||||
@ -183,17 +188,10 @@ export const getValidatorFailedTransactionsForMessage = async ({
|
|||||||
account,
|
account,
|
||||||
to,
|
to,
|
||||||
messageData,
|
messageData,
|
||||||
startTimestamp,
|
startBlock,
|
||||||
endTimestamp
|
endBlock
|
||||||
}: GetFailedTransactionParams): Promise<APITransaction[]> => {
|
}: GetTransactionParams): Promise<APITransaction[]> => {
|
||||||
const failedTransactions = await getFailedTransactions(
|
const failedTransactions = await getFailedTransactions(account, to, startBlock, endBlock, HOME_EXPLORER_API)
|
||||||
account,
|
|
||||||
to,
|
|
||||||
startTimestamp,
|
|
||||||
endTimestamp,
|
|
||||||
HOME_EXPLORER_API,
|
|
||||||
fetchAccountTransactionsFromBlockscout
|
|
||||||
)
|
|
||||||
|
|
||||||
return filterValidatorSignatureTransaction(failedTransactions, messageData)
|
return filterValidatorSignatureTransaction(failedTransactions, messageData)
|
||||||
}
|
}
|
||||||
@ -202,33 +200,19 @@ export const getValidatorSuccessTransactionsForMessage = async ({
|
|||||||
account,
|
account,
|
||||||
to,
|
to,
|
||||||
messageData,
|
messageData,
|
||||||
startTimestamp,
|
startBlock,
|
||||||
endTimestamp
|
endBlock
|
||||||
}: GetFailedTransactionParams): Promise<APITransaction[]> => {
|
}: GetTransactionParams): Promise<APITransaction[]> => {
|
||||||
const transactions = await getSuccessTransactions(
|
const transactions = await getSuccessTransactions(account, to, startBlock, endBlock, HOME_EXPLORER_API)
|
||||||
account,
|
|
||||||
to,
|
|
||||||
startTimestamp,
|
|
||||||
endTimestamp,
|
|
||||||
HOME_EXPLORER_API,
|
|
||||||
fetchAccountTransactionsFromBlockscout
|
|
||||||
)
|
|
||||||
|
|
||||||
return filterValidatorSignatureTransaction(transactions, messageData)
|
return filterValidatorSignatureTransaction(transactions, messageData)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getExecutionFailedTransactionForMessage = async (
|
export const getExecutionFailedTransactionForMessage = async (
|
||||||
{ account, to, messageData, startTimestamp, endTimestamp }: GetFailedTransactionParams,
|
{ account, to, messageData, startBlock, endBlock }: GetTransactionParams,
|
||||||
getFailedTransactionsMethod = getFailedTransactions
|
getFailedTransactionsMethod = getFailedTransactions
|
||||||
): Promise<APITransaction[]> => {
|
): Promise<APITransaction[]> => {
|
||||||
const failedTransactions = await getFailedTransactionsMethod(
|
const failedTransactions = await getFailedTransactionsMethod(account, to, startBlock, endBlock, FOREIGN_EXPLORER_API)
|
||||||
account,
|
|
||||||
to,
|
|
||||||
startTimestamp,
|
|
||||||
endTimestamp,
|
|
||||||
FOREIGN_EXPLORER_API,
|
|
||||||
fetchAccountTransactions(FOREIGN_EXPLORER_API)
|
|
||||||
)
|
|
||||||
|
|
||||||
const messageDataValue = messageData.replace('0x', '')
|
const messageDataValue = messageData.replace('0x', '')
|
||||||
return failedTransactions.filter(t => t.input.includes(EXECUTE_SIGNATURES_HASH) && t.input.includes(messageDataValue))
|
return failedTransactions.filter(t => t.input.includes(EXECUTE_SIGNATURES_HASH) && t.input.includes(messageDataValue))
|
||||||
|
@ -31,7 +31,6 @@ export const getCollectedSignaturesEvent = async (
|
|||||||
if (filteredEvents.length) {
|
if (filteredEvents.length) {
|
||||||
const event = filteredEvents[0]
|
const event = filteredEvents[0]
|
||||||
setCollectedSignaturesEvent(event)
|
setCollectedSignaturesEvent(event)
|
||||||
homeBlockNumberProvider.stop()
|
|
||||||
} else {
|
} else {
|
||||||
const newFromBlock = currentBlock ? securedToBlock : fromBlock
|
const newFromBlock = currentBlock ? securedToBlock : fromBlock
|
||||||
const newToBlock = currentBlock ? toBlock + BLOCK_RANGE : toBlock
|
const newToBlock = currentBlock ? toBlock + BLOCK_RANGE : toBlock
|
||||||
|
@ -1,12 +1,7 @@
|
|||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
import { Contract } from 'web3-eth-contract'
|
import { Contract } from 'web3-eth-contract'
|
||||||
import { HOME_RPC_POLLING_INTERVAL, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
import { HOME_RPC_POLLING_INTERVAL, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
||||||
import {
|
import { GetTransactionParams, APITransaction, APIPendingTransaction, GetPendingTransactionParams } from './explorer'
|
||||||
GetFailedTransactionParams,
|
|
||||||
APITransaction,
|
|
||||||
APIPendingTransaction,
|
|
||||||
GetPendingTransactionParams
|
|
||||||
} from './explorer'
|
|
||||||
import { getAffirmationsSigned, getMessagesSigned } from './contract'
|
import { getAffirmationsSigned, getMessagesSigned } from './contract'
|
||||||
import {
|
import {
|
||||||
getValidatorConfirmation,
|
getValidatorConfirmation,
|
||||||
@ -43,12 +38,12 @@ export const getConfirmationsForTx = async (
|
|||||||
setSignatureCollected: Function,
|
setSignatureCollected: Function,
|
||||||
waitingBlocksResolved: boolean,
|
waitingBlocksResolved: boolean,
|
||||||
subscriptions: number[],
|
subscriptions: number[],
|
||||||
timestamp: number,
|
startBlock: number,
|
||||||
getFailedTransactions: (args: GetFailedTransactionParams) => Promise<APITransaction[]>,
|
getFailedTransactions: (args: GetTransactionParams) => Promise<APITransaction[]>,
|
||||||
setFailedConfirmations: Function,
|
setFailedConfirmations: Function,
|
||||||
getPendingTransactions: (args: GetPendingTransactionParams) => Promise<APIPendingTransaction[]>,
|
getPendingTransactions: (args: GetPendingTransactionParams) => Promise<APIPendingTransaction[]>,
|
||||||
setPendingConfirmations: Function,
|
setPendingConfirmations: Function,
|
||||||
getSuccessTransactions: (args: GetFailedTransactionParams) => Promise<APITransaction[]>
|
getSuccessTransactions: (args: GetTransactionParams) => Promise<APITransaction[]>
|
||||||
) => {
|
) => {
|
||||||
if (!web3 || !validatorList || !validatorList.length || !bridgeContract || !waitingBlocksResolved) return
|
if (!web3 || !validatorList || !validatorList.length || !bridgeContract || !waitingBlocksResolved) return
|
||||||
|
|
||||||
@ -102,7 +97,7 @@ export const getConfirmationsForTx = async (
|
|||||||
// Check if confirmation failed
|
// Check if confirmation failed
|
||||||
const validatorFailedConfirmationsChecks = await Promise.all(
|
const validatorFailedConfirmationsChecks = await Promise.all(
|
||||||
undefinedConfirmations.map(
|
undefinedConfirmations.map(
|
||||||
getValidatorFailedTransaction(bridgeContract, messageData, timestamp, getFailedTransactions)
|
getValidatorFailedTransaction(bridgeContract, messageData, startBlock, getFailedTransactions)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
const validatorFailedConfirmations = validatorFailedConfirmationsChecks.filter(
|
const validatorFailedConfirmations = validatorFailedConfirmationsChecks.filter(
|
||||||
@ -136,7 +131,7 @@ export const getConfirmationsForTx = async (
|
|||||||
// get transactions from success signatures
|
// get transactions from success signatures
|
||||||
const successConfirmationWithData = await Promise.all(
|
const successConfirmationWithData = await Promise.all(
|
||||||
successConfirmations.map(
|
successConfirmations.map(
|
||||||
getSuccessExecutionTransaction(web3, bridgeContract, fromHome, messageData, timestamp, getSuccessTransactions)
|
getSuccessExecutionTransaction(web3, bridgeContract, fromHome, messageData, startBlock, getSuccessTransactions)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -162,7 +157,7 @@ export const getConfirmationsForTx = async (
|
|||||||
setSignatureCollected,
|
setSignatureCollected,
|
||||||
waitingBlocksResolved,
|
waitingBlocksResolved,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
timestamp,
|
startBlock,
|
||||||
getFailedTransactions,
|
getFailedTransactions,
|
||||||
setFailedConfirmations,
|
setFailedConfirmations,
|
||||||
getPendingTransactions,
|
getPendingTransactions,
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
import { Contract, EventData } from 'web3-eth-contract'
|
import { Contract, EventData } from 'web3-eth-contract'
|
||||||
import Web3 from 'web3'
|
import Web3 from 'web3'
|
||||||
import { CACHE_KEY_EXECUTION_FAILED, THREE_DAYS_TIMESTAMP, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
import { CACHE_KEY_EXECUTION_FAILED, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
||||||
import { ExecutionData } from '../hooks/useMessageConfirmations'
|
import { ExecutionData } from '../hooks/useMessageConfirmations'
|
||||||
import {
|
import { APIPendingTransaction, APITransaction, GetTransactionParams, GetPendingTransactionParams } from './explorer'
|
||||||
APIPendingTransaction,
|
|
||||||
APITransaction,
|
|
||||||
GetFailedTransactionParams,
|
|
||||||
GetPendingTransactionParams
|
|
||||||
} from './explorer'
|
|
||||||
import { getBlock, MessageObject } from './web3'
|
import { getBlock, MessageObject } from './web3'
|
||||||
import validatorsCache from '../services/ValidatorsCache'
|
import validatorsCache from '../services/ValidatorsCache'
|
||||||
|
import { foreignBlockNumberProvider, homeBlockNumberProvider } from '../services/BlockNumberProvider'
|
||||||
|
|
||||||
export const getSuccessExecutionData = async (contract: Contract, eventName: string, web3: Web3, messageId: string) => {
|
export const getSuccessExecutionData = async (contract: Contract, eventName: string, web3: Web3, messageId: string) => {
|
||||||
// Since it filters by the message id, only one event will be fetched
|
// Since it filters by the message id, only one event will be fetched
|
||||||
@ -43,6 +39,7 @@ export const getSuccessExecutionData = async (contract: Contract, eventName: str
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const getFinalizationEvent = async (
|
export const getFinalizationEvent = async (
|
||||||
|
fromHome: boolean,
|
||||||
contract: Maybe<Contract>,
|
contract: Maybe<Contract>,
|
||||||
eventName: string,
|
eventName: string,
|
||||||
web3: Maybe<Web3>,
|
web3: Maybe<Web3>,
|
||||||
@ -51,9 +48,9 @@ export const getFinalizationEvent = async (
|
|||||||
message: MessageObject,
|
message: MessageObject,
|
||||||
interval: number,
|
interval: number,
|
||||||
subscriptions: number[],
|
subscriptions: number[],
|
||||||
timestamp: number,
|
startBlock: number,
|
||||||
collectedSignaturesEvent: Maybe<EventData>,
|
collectedSignaturesEvent: Maybe<EventData>,
|
||||||
getFailedExecution: (args: GetFailedTransactionParams) => Promise<APITransaction[]>,
|
getFailedExecution: (args: GetTransactionParams) => Promise<APITransaction[]>,
|
||||||
setFailedExecution: Function,
|
setFailedExecution: Function,
|
||||||
getPendingExecution: (args: GetPendingTransactionParams) => Promise<APIPendingTransaction[]>,
|
getPendingExecution: (args: GetPendingTransactionParams) => Promise<APIPendingTransaction[]>,
|
||||||
setPendingExecution: Function,
|
setPendingExecution: Function,
|
||||||
@ -92,14 +89,15 @@ export const getFinalizationEvent = async (
|
|||||||
} else {
|
} else {
|
||||||
const validatorExecutionCacheKey = `${CACHE_KEY_EXECUTION_FAILED}${validator}-${message.id}`
|
const validatorExecutionCacheKey = `${CACHE_KEY_EXECUTION_FAILED}${validator}-${message.id}`
|
||||||
const failedFromCache = validatorsCache.get(validatorExecutionCacheKey)
|
const failedFromCache = validatorsCache.get(validatorExecutionCacheKey)
|
||||||
|
const blockProvider = fromHome ? foreignBlockNumberProvider : homeBlockNumberProvider
|
||||||
|
|
||||||
if (!failedFromCache) {
|
if (!failedFromCache) {
|
||||||
const failedTransactions = await getFailedExecution({
|
const failedTransactions = await getFailedExecution({
|
||||||
account: validator,
|
account: validator,
|
||||||
to: contract.options.address,
|
to: contract.options.address,
|
||||||
messageData: message.data,
|
messageData: message.data,
|
||||||
startTimestamp: timestamp,
|
startBlock,
|
||||||
endTimestamp: timestamp + THREE_DAYS_TIMESTAMP
|
endBlock: blockProvider.get() || 0
|
||||||
})
|
})
|
||||||
|
|
||||||
if (failedTransactions.length > 0) {
|
if (failedTransactions.length > 0) {
|
||||||
@ -125,6 +123,7 @@ export const getFinalizationEvent = async (
|
|||||||
const timeoutId = setTimeout(
|
const timeoutId = setTimeout(
|
||||||
() =>
|
() =>
|
||||||
getFinalizationEvent(
|
getFinalizationEvent(
|
||||||
|
fromHome,
|
||||||
contract,
|
contract,
|
||||||
eventName,
|
eventName,
|
||||||
web3,
|
web3,
|
||||||
@ -133,7 +132,7 @@ export const getFinalizationEvent = async (
|
|||||||
message,
|
message,
|
||||||
interval,
|
interval,
|
||||||
subscriptions,
|
subscriptions,
|
||||||
timestamp,
|
startBlock,
|
||||||
collectedSignaturesEvent,
|
collectedSignaturesEvent,
|
||||||
getFailedExecution,
|
getFailedExecution,
|
||||||
setFailedExecution,
|
setFailedExecution,
|
||||||
|
@ -16,7 +16,6 @@ export const checkSignaturesWaitingForBLocks = async (
|
|||||||
if (currentBlock && currentBlock >= targetBlock) {
|
if (currentBlock && currentBlock >= targetBlock) {
|
||||||
setWaitingBlocksResolved(true)
|
setWaitingBlocksResolved(true)
|
||||||
setWaitingStatus(false)
|
setWaitingStatus(false)
|
||||||
blockProvider.stop()
|
|
||||||
} else {
|
} else {
|
||||||
let nextInterval = interval
|
let nextInterval = interval
|
||||||
if (!currentBlock) {
|
if (!currentBlock) {
|
||||||
|
@ -2,18 +2,9 @@ import Web3 from 'web3'
|
|||||||
import { Contract } from 'web3-eth-contract'
|
import { Contract } from 'web3-eth-contract'
|
||||||
import { BasicConfirmationParam, ConfirmationParam } from '../hooks/useMessageConfirmations'
|
import { BasicConfirmationParam, ConfirmationParam } from '../hooks/useMessageConfirmations'
|
||||||
import validatorsCache from '../services/ValidatorsCache'
|
import validatorsCache from '../services/ValidatorsCache'
|
||||||
import {
|
import { CACHE_KEY_FAILED, CACHE_KEY_SUCCESS, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
||||||
CACHE_KEY_FAILED,
|
import { APIPendingTransaction, APITransaction, GetTransactionParams, GetPendingTransactionParams } from './explorer'
|
||||||
CACHE_KEY_SUCCESS,
|
import { homeBlockNumberProvider } from '../services/BlockNumberProvider'
|
||||||
ONE_DAY_TIMESTAMP,
|
|
||||||
VALIDATOR_CONFIRMATION_STATUS
|
|
||||||
} from '../config/constants'
|
|
||||||
import {
|
|
||||||
APIPendingTransaction,
|
|
||||||
APITransaction,
|
|
||||||
GetFailedTransactionParams,
|
|
||||||
GetPendingTransactionParams
|
|
||||||
} from './explorer'
|
|
||||||
|
|
||||||
export const getValidatorConfirmation = (
|
export const getValidatorConfirmation = (
|
||||||
web3: Web3,
|
web3: Web3,
|
||||||
@ -50,8 +41,8 @@ export const getSuccessExecutionTransaction = (
|
|||||||
bridgeContract: Contract,
|
bridgeContract: Contract,
|
||||||
fromHome: boolean,
|
fromHome: boolean,
|
||||||
messageData: string,
|
messageData: string,
|
||||||
timestamp: number,
|
startBlock: number,
|
||||||
getSuccessTransactions: (args: GetFailedTransactionParams) => Promise<APITransaction[]>
|
getSuccessTransactions: (args: GetTransactionParams) => Promise<APITransaction[]>
|
||||||
) => async (validatorData: BasicConfirmationParam): Promise<ConfirmationParam> => {
|
) => async (validatorData: BasicConfirmationParam): Promise<ConfirmationParam> => {
|
||||||
const { validator } = validatorData
|
const { validator } = validatorData
|
||||||
const validatorCacheKey = `${CACHE_KEY_SUCCESS}${validatorData.validator}-${messageData}`
|
const validatorCacheKey = `${CACHE_KEY_SUCCESS}${validatorData.validator}-${messageData}`
|
||||||
@ -65,8 +56,8 @@ export const getSuccessExecutionTransaction = (
|
|||||||
account: validatorData.validator,
|
account: validatorData.validator,
|
||||||
to: bridgeContract.options.address,
|
to: bridgeContract.options.address,
|
||||||
messageData,
|
messageData,
|
||||||
startTimestamp: timestamp,
|
startBlock,
|
||||||
endTimestamp: timestamp + ONE_DAY_TIMESTAMP
|
endBlock: homeBlockNumberProvider.get() || 0
|
||||||
})
|
})
|
||||||
|
|
||||||
let txHashTimestamp = 0
|
let txHashTimestamp = 0
|
||||||
@ -98,8 +89,8 @@ export const getSuccessExecutionTransaction = (
|
|||||||
export const getValidatorFailedTransaction = (
|
export const getValidatorFailedTransaction = (
|
||||||
bridgeContract: Contract,
|
bridgeContract: Contract,
|
||||||
messageData: string,
|
messageData: string,
|
||||||
timestamp: number,
|
startBlock: number,
|
||||||
getFailedTransactions: (args: GetFailedTransactionParams) => Promise<APITransaction[]>
|
getFailedTransactions: (args: GetTransactionParams) => Promise<APITransaction[]>
|
||||||
) => async (validatorData: BasicConfirmationParam): Promise<ConfirmationParam> => {
|
) => async (validatorData: BasicConfirmationParam): Promise<ConfirmationParam> => {
|
||||||
const validatorCacheKey = `${CACHE_KEY_FAILED}${validatorData.validator}-${messageData}`
|
const validatorCacheKey = `${CACHE_KEY_FAILED}${validatorData.validator}-${messageData}`
|
||||||
const failedFromCache = validatorsCache.getData(validatorCacheKey)
|
const failedFromCache = validatorsCache.getData(validatorCacheKey)
|
||||||
@ -112,8 +103,8 @@ export const getValidatorFailedTransaction = (
|
|||||||
account: validatorData.validator,
|
account: validatorData.validator,
|
||||||
to: bridgeContract.options.address,
|
to: bridgeContract.options.address,
|
||||||
messageData,
|
messageData,
|
||||||
startTimestamp: timestamp,
|
startBlock,
|
||||||
endTimestamp: timestamp + ONE_DAY_TIMESTAMP
|
endBlock: homeBlockNumberProvider.get() || 0
|
||||||
})
|
})
|
||||||
const newStatus =
|
const newStatus =
|
||||||
failedTransactions.length > 0 ? VALIDATOR_CONFIRMATION_STATUS.FAILED : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED
|
failedTransactions.length > 0 ? VALIDATOR_CONFIRMATION_STATUS.FAILED : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED
|
||||||
|
Loading…
Reference in New Issue
Block a user