Add new status for when there is no registered activity by validators (#401)

This commit is contained in:
Gerardo Nardelli 2020-07-20 18:44:29 -03:00 committed by GitHub
parent 77bc6c662a
commit fdfa5cd7af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 259 additions and 35 deletions

@ -49,7 +49,7 @@ export const ConfirmationsContainer = ({ message, receipt, fromHome, timestamp }
} = useStateProvider() } = useStateProvider()
const { requiredSignatures, validatorList } = useValidatorContract({ fromHome, receipt }) const { requiredSignatures, validatorList } = useValidatorContract({ fromHome, receipt })
const { blockConfirmations } = useBlockConfirmations({ fromHome, receipt }) const { blockConfirmations } = useBlockConfirmations({ fromHome, receipt })
const { confirmations, status, executionData, signatureCollected } = useMessageConfirmations({ const { confirmations, status, executionData, signatureCollected, waitingBlocksResolved } = useMessageConfirmations({
message, message,
receipt, receipt,
fromHome, fromHome,
@ -100,6 +100,7 @@ export const ConfirmationsContainer = ({ message, receipt, fromHome, timestamp }
confirmations={confirmations} confirmations={confirmations}
requiredSignatures={requiredSignatures} requiredSignatures={requiredSignatures}
validatorList={validatorList} validatorList={validatorList}
waitingBlocksResolved={waitingBlocksResolved}
/> />
{signatureCollected && <ExecutionConfirmation executionData={executionData} isHome={!fromHome} />} {signatureCollected && <ExecutionConfirmation executionData={executionData} isHome={!fromHome} />}
</StyledConfirmationContainer> </StyledConfirmationContainer>

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks' import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks'
import { useWindowWidth } from '@react-hook/window-size' import { useWindowWidth } from '@react-hook/window-size'
import { VALIDATOR_CONFIRMATION_STATUS } from '../config/constants' import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
import { SimpleLoading } from './commons/Loading' import { SimpleLoading } from './commons/Loading'
import styled from 'styled-components' import styled from 'styled-components'
import { ExecutionData } from '../hooks/useMessageConfirmations' import { ExecutionData } from '../hooks/useMessageConfirmations'
@ -35,7 +35,11 @@ export const ExecutionConfirmation = ({ executionData, isHome }: ExecutionConfir
case VALIDATOR_CONFIRMATION_STATUS.WAITING: case VALIDATOR_CONFIRMATION_STATUS.WAITING:
return <GreyLabel>{validatorStatus}</GreyLabel> return <GreyLabel>{validatorStatus}</GreyLabel>
default: default:
return <SimpleLoading /> return executionData.validator ? (
<GreyLabel>{VALIDATOR_CONFIRMATION_STATUS.WAITING}</GreyLabel>
) : (
<SimpleLoading />
)
} }
} }
@ -54,9 +58,15 @@ export const ExecutionConfirmation = ({ executionData, isHome }: ExecutionConfir
<td>{formattedValidator ? formattedValidator : <SimpleLoading />}</td> <td>{formattedValidator ? formattedValidator : <SimpleLoading />}</td>
<StatusTd className="text-center">{getExecutionStatusElement(executionData.status)}</StatusTd> <StatusTd className="text-center">{getExecutionStatusElement(executionData.status)}</StatusTd>
<AgeTd className="text-center"> <AgeTd className="text-center">
<ExplorerTxLink href={txExplorerLink} target="_blank"> {executionData.timestamp > 0 ? (
{executionData.timestamp > 0 ? formatTimestamp(executionData.timestamp) : ''} <ExplorerTxLink href={txExplorerLink} target="_blank">
</ExplorerTxLink> {formatTimestamp(executionData.timestamp)}
</ExplorerTxLink>
) : executionData.status === VALIDATOR_CONFIRMATION_STATUS.WAITING ? (
''
) : (
SEARCHING_TX
)}
</AgeTd> </AgeTd>
</tr> </tr>
</tbody> </tbody>

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks' import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks'
import { useWindowWidth } from '@react-hook/window-size' import { useWindowWidth } from '@react-hook/window-size'
import { VALIDATOR_CONFIRMATION_STATUS } from '../config/constants' import { SEARCHING_TX, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
import { SimpleLoading } from './commons/Loading' import { SimpleLoading } from './commons/Loading'
import styled from 'styled-components' import styled from 'styled-components'
import { ConfirmationParam } from '../hooks/useMessageConfirmations' import { ConfirmationParam } from '../hooks/useMessageConfirmations'
@ -17,12 +17,14 @@ export interface ValidatorsConfirmationsParams {
confirmations: Array<ConfirmationParam> confirmations: Array<ConfirmationParam>
requiredSignatures: number requiredSignatures: number
validatorList: string[] validatorList: string[]
waitingBlocksResolved: boolean
} }
export const ValidatorsConfirmations = ({ export const ValidatorsConfirmations = ({
confirmations, confirmations,
requiredSignatures, requiredSignatures,
validatorList validatorList,
waitingBlocksResolved
}: ValidatorsConfirmationsParams) => { }: ValidatorsConfirmationsParams) => {
const windowWidth = useWindowWidth() const windowWidth = useWindowWidth()
@ -37,7 +39,11 @@ export const ValidatorsConfirmations = ({
case VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED: case VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED:
return <GreyLabel>{validatorStatus}</GreyLabel> return <GreyLabel>{validatorStatus}</GreyLabel>
default: default:
return <SimpleLoading /> return waitingBlocksResolved ? (
<GreyLabel>{VALIDATOR_CONFIRMATION_STATUS.WAITING}</GreyLabel>
) : (
<SimpleLoading />
)
} }
} }
@ -60,7 +66,12 @@ export const ValidatorsConfirmations = ({
const elementIfNoTimestamp = const elementIfNoTimestamp =
displayedStatus !== VALIDATOR_CONFIRMATION_STATUS.WAITING && displayedStatus !== VALIDATOR_CONFIRMATION_STATUS.WAITING &&
displayedStatus !== VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED ? ( displayedStatus !== VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED ? (
<SimpleLoading /> (displayedStatus === VALIDATOR_CONFIRMATION_STATUS.UNDEFINED || displayedStatus === '') &&
waitingBlocksResolved ? (
SEARCHING_TX
) : (
<SimpleLoading />
)
) : ( ) : (
'' ''
) )
@ -69,11 +80,13 @@ export const ValidatorsConfirmations = ({
<td>{windowWidth < 850 ? formatTxHash(validator) : validator}</td> <td>{windowWidth < 850 ? formatTxHash(validator) : validator}</td>
<StatusTd className="text-center">{getValidatorStatusElement(displayedStatus)}</StatusTd> <StatusTd className="text-center">{getValidatorStatusElement(displayedStatus)}</StatusTd>
<AgeTd className="text-center"> <AgeTd className="text-center">
<ExplorerTxLink href={explorerLink} target="_blank"> {confirmation && confirmation.timestamp > 0 ? (
{confirmation && confirmation.timestamp > 0 <ExplorerTxLink href={explorerLink} target="_blank">
? formatTimestamp(confirmation.timestamp) {formatTimestamp(confirmation.timestamp)}
: elementIfNoTimestamp} </ExplorerTxLink>
</ExplorerTxLink> ) : (
elementIfNoTimestamp
)}
</AgeTd> </AgeTd>
</tr> </tr>
) )

@ -45,6 +45,7 @@ export const CONFIRMATIONS_STATUS = {
EXECUTION_WAITING: 'EXECUTION_WAITING', EXECUTION_WAITING: 'EXECUTION_WAITING',
FAILED: 'FAILED', FAILED: 'FAILED',
PENDING: 'PENDING', PENDING: 'PENDING',
SEARCHING: 'SEARCHING',
WAITING_VALIDATORS: 'WAITING_VALIDATORS', WAITING_VALIDATORS: 'WAITING_VALIDATORS',
WAITING_CHAIN: 'WAITING_CHAIN', WAITING_CHAIN: 'WAITING_CHAIN',
UNDEFINED: 'UNDEFINED' UNDEFINED: 'UNDEFINED'
@ -58,3 +59,5 @@ export const VALIDATOR_CONFIRMATION_STATUS = {
NOT_REQUIRED: 'Not required', NOT_REQUIRED: 'Not required',
UNDEFINED: 'UNDEFINED' UNDEFINED: 'UNDEFINED'
} }
export const SEARCHING_TX = 'Searching Transaction...'

@ -14,6 +14,7 @@ export const CONFIRMATIONS_STATUS_LABEL: { [key: string]: string } = {
FAILED: 'Failed', FAILED: 'Failed',
PENDING: 'Pending', PENDING: 'Pending',
WAITING_VALIDATORS: 'Waiting', WAITING_VALIDATORS: 'Waiting',
SEARCHING: 'Waiting',
WAITING_CHAIN: 'Waiting' WAITING_CHAIN: 'Waiting'
} }
@ -26,6 +27,7 @@ export const CONFIRMATIONS_STATUS_LABEL_HOME: { [key: string]: string } = {
FAILED: 'Confirmation Failed', FAILED: 'Confirmation Failed',
PENDING: 'Confirmation Pending', PENDING: 'Confirmation Pending',
WAITING_VALIDATORS: 'Confirmation Waiting', WAITING_VALIDATORS: 'Confirmation Waiting',
SEARCHING: 'Confirmation Waiting',
WAITING_CHAIN: 'Confirmation Waiting' WAITING_CHAIN: 'Confirmation Waiting'
} }
@ -39,7 +41,9 @@ export const CONFIRMATIONS_STATUS_DESCRIPTION: { [key: string]: string } = {
PENDING: PENDING:
'The specified transaction was included in a block. A\nmajority of validators sent confirmations which have\nnot yet been added to a block.', 'The specified transaction was included in a block. A\nmajority of validators sent confirmations which have\nnot yet been added to a block.',
WAITING_VALIDATORS: WAITING_VALIDATORS:
'The specified transaction was included in a block.\nSome validators have sent confirmations, others are\nwaiting for chain finalization.', 'The specified transaction was included in a block.\nSome validators have sent confirmations, others are\nwaiting for chain finalization.\nCheck status again after a few blocks. If the issue still persists contact to the validators by messaging on %linkhttps://forum.poa.network/c/support',
SEARCHING:
'The specified transaction was included in a block. The app is looking for confirmations. Either\n1. Validators are waiting for chain finalization before sending their signatures.\n2. Validators are not active.\n3. The bridge was stopped.\nCheck status again after a few blocks. If the issue still persists contact to the validators by messaging on %linkhttps://forum.poa.network/c/support',
WAITING_CHAIN: WAITING_CHAIN:
'The specified transaction was included in a block.\nValidators are waiting for chain finalization before\nsending their confirmations.' 'The specified transaction was included in a block.\nValidators are waiting for chain finalization before\nsending their confirmations.'
} }
@ -60,7 +64,9 @@ export const CONFIRMATIONS_STATUS_DESCRIPTION_HOME: { [key: string]: string } =
PENDING: PENDING:
'The specified transaction was included in a block.\nA majority of validators sent signatures which have not\nyet been added to a block.', 'The specified transaction was included in a block.\nA majority of validators sent signatures which have not\nyet been added to a block.',
WAITING_VALIDATORS: WAITING_VALIDATORS:
'The specified transaction was included in a block.\nSome validators have sent signatures, others are\nwaiting for chain finalization.', 'The specified transaction was included in a block.\nSome validators have sent signatures, others are\nwaiting for chain finalization.\nCheck status again after a few blocks. If the issue still persists contact to the validators by messaging on %linkhttps://forum.poa.network/c/support',
SEARCHING:
'The specified transaction was included in a block. The app is looking for confirmations. Either\n1. Validators are waiting for chain finalization before sending their signatures.\n2. Validators are not active.\n3. The bridge was stopped.\nCheck status again after a few blocks. If the issue still persists contact to the validators by messaging on %linkhttps://forum.poa.network/c/support',
WAITING_CHAIN: WAITING_CHAIN:
'The specified transaction was included in a block.\nValidators are waiting for chain finalization\nbefore sending their signatures.' 'The specified transaction was included in a block.\nValidators are waiting for chain finalization\nbefore sending their signatures.'
} }

@ -329,7 +329,7 @@ export const useMessageConfirmations = ({
} else if (waitingBlocksForExecutionResolved) { } else if (waitingBlocksForExecutionResolved) {
setStatus(CONFIRMATIONS_STATUS.EXECUTION_WAITING) setStatus(CONFIRMATIONS_STATUS.EXECUTION_WAITING)
} else { } else {
setStatus(CONFIRMATIONS_STATUS.UNDEFINED) setStatus(CONFIRMATIONS_STATUS.EXECUTION_WAITING)
} }
} else { } else {
setStatus(CONFIRMATIONS_STATUS.UNDEFINED) setStatus(CONFIRMATIONS_STATUS.UNDEFINED)
@ -342,6 +342,8 @@ export const useMessageConfirmations = ({
setStatus(CONFIRMATIONS_STATUS.PENDING) setStatus(CONFIRMATIONS_STATUS.PENDING)
} else if (waitingBlocksResolved && existsConfirmation(confirmations)) { } else if (waitingBlocksResolved && existsConfirmation(confirmations)) {
setStatus(CONFIRMATIONS_STATUS.WAITING_VALIDATORS) setStatus(CONFIRMATIONS_STATUS.WAITING_VALIDATORS)
} else if (waitingBlocksResolved) {
setStatus(CONFIRMATIONS_STATUS.SEARCHING)
} else { } else {
setStatus(CONFIRMATIONS_STATUS.UNDEFINED) setStatus(CONFIRMATIONS_STATUS.UNDEFINED)
} }
@ -366,6 +368,7 @@ export const useMessageConfirmations = ({
confirmations, confirmations,
status, status,
signatureCollected, signatureCollected,
executionData executionData,
waitingBlocksResolved
} }
} }

@ -104,12 +104,15 @@ describe('getConfirmationsForTx', () => {
expect(getValidatorConfirmation).toBeCalledTimes(1) expect(getValidatorConfirmation).toBeCalledTimes(1)
expect(getValidatorSuccessTransaction).toBeCalledTimes(1) expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
expect(setSignatureCollected).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1)
expect(setSignatureCollected.mock.calls[0][0]).toEqual(true)
expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(getValidatorFailedTransaction).toBeCalledTimes(1)
expect(setFailedConfirmations).toBeCalledTimes(0) expect(setFailedConfirmations).toBeCalledTimes(1)
expect(setFailedConfirmations.mock.calls[0][0]).toEqual(false)
expect(getValidatorPendingTransaction).toBeCalledTimes(0) expect(getValidatorPendingTransaction).toBeCalledTimes(0)
expect(setPendingConfirmations).toBeCalledTimes(0) expect(setPendingConfirmations).toBeCalledTimes(1)
expect(setPendingConfirmations.mock.calls[0][0]).toEqual(false)
expect(setResult.mock.calls[0][0]()).toEqual( expect(setResult.mock.calls[0][0]()).toEqual(
expect.arrayContaining([ expect.arrayContaining([
@ -179,13 +182,16 @@ describe('getConfirmationsForTx', () => {
expect(setResult).toBeCalledTimes(2) expect(setResult).toBeCalledTimes(2)
expect(getValidatorConfirmation).toBeCalledTimes(1) expect(getValidatorConfirmation).toBeCalledTimes(1)
expect(getValidatorSuccessTransaction).toBeCalledTimes(1) expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
expect(setSignatureCollected).toBeCalledTimes(0) expect(setSignatureCollected).toBeCalledTimes(1)
expect(setSignatureCollected.mock.calls[0][0]).toEqual(false)
expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(getValidatorFailedTransaction).toBeCalledTimes(1)
expect(setFailedConfirmations).toBeCalledTimes(0) expect(setFailedConfirmations).toBeCalledTimes(1)
expect(setFailedConfirmations.mock.calls[0][0]).toEqual(false)
expect(getValidatorPendingTransaction).toBeCalledTimes(1) expect(getValidatorPendingTransaction).toBeCalledTimes(1)
expect(setPendingConfirmations).toBeCalledTimes(0) expect(setPendingConfirmations).toBeCalledTimes(1)
expect(setPendingConfirmations.mock.calls[0][0]).toEqual(false)
}) })
test('should set validator confirmations status, validator transactions and not retry', async () => { test('should set validator confirmations status, validator transactions and not retry', async () => {
getValidatorConfirmation.mockImplementation(() => async (validator: string) => ({ getValidatorConfirmation.mockImplementation(() => async (validator: string) => ({
@ -242,12 +248,15 @@ describe('getConfirmationsForTx', () => {
expect(getValidatorConfirmation).toBeCalledTimes(1) expect(getValidatorConfirmation).toBeCalledTimes(1)
expect(getValidatorSuccessTransaction).toBeCalledTimes(1) expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
expect(setSignatureCollected).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1)
expect(setSignatureCollected.mock.calls[0][0]).toEqual(true)
expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(getValidatorFailedTransaction).toBeCalledTimes(1)
expect(setFailedConfirmations).toBeCalledTimes(0) expect(setFailedConfirmations).toBeCalledTimes(1)
expect(setFailedConfirmations.mock.calls[0][0]).toEqual(false)
expect(getValidatorPendingTransaction).toBeCalledTimes(0) expect(getValidatorPendingTransaction).toBeCalledTimes(0)
expect(setPendingConfirmations).toBeCalledTimes(0) expect(setPendingConfirmations).toBeCalledTimes(1)
expect(setPendingConfirmations.mock.calls[0][0]).toEqual(false)
expect(setResult.mock.calls[0][0]()).toEqual( expect(setResult.mock.calls[0][0]()).toEqual(
expect.arrayContaining([ expect.arrayContaining([
@ -327,12 +336,15 @@ describe('getConfirmationsForTx', () => {
expect(getValidatorConfirmation).toBeCalledTimes(1) expect(getValidatorConfirmation).toBeCalledTimes(1)
expect(getValidatorSuccessTransaction).toBeCalledTimes(1) expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
expect(setSignatureCollected).toBeCalledTimes(1) expect(setSignatureCollected).toBeCalledTimes(1)
expect(setSignatureCollected.mock.calls[0][0]).toEqual(true)
expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(getValidatorFailedTransaction).toBeCalledTimes(1)
expect(setFailedConfirmations).toBeCalledTimes(0) expect(setFailedConfirmations).toBeCalledTimes(1)
expect(setFailedConfirmations.mock.calls[0][0]).toEqual(false)
expect(getValidatorPendingTransaction).toBeCalledTimes(0) expect(getValidatorPendingTransaction).toBeCalledTimes(0)
expect(setPendingConfirmations).toBeCalledTimes(0) expect(setPendingConfirmations).toBeCalledTimes(1)
expect(setPendingConfirmations.mock.calls[0][0]).toEqual(false)
expect(setResult.mock.calls[0][0]()).toEqual( expect(setResult.mock.calls[0][0]()).toEqual(
expect.arrayContaining([ expect.arrayContaining([
@ -414,13 +426,16 @@ describe('getConfirmationsForTx', () => {
expect(setResult).toBeCalledTimes(2) expect(setResult).toBeCalledTimes(2)
expect(getValidatorConfirmation).toBeCalledTimes(1) expect(getValidatorConfirmation).toBeCalledTimes(1)
expect(getValidatorSuccessTransaction).toBeCalledTimes(1) expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
expect(setSignatureCollected).toBeCalledTimes(0) expect(setSignatureCollected).toBeCalledTimes(1)
expect(setSignatureCollected.mock.calls[0][0]).toEqual(false)
expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(getValidatorFailedTransaction).toBeCalledTimes(1)
expect(setFailedConfirmations).toBeCalledTimes(0) expect(setFailedConfirmations).toBeCalledTimes(1)
expect(setFailedConfirmations.mock.calls[0][0]).toEqual(false)
expect(getValidatorPendingTransaction).toBeCalledTimes(1) expect(getValidatorPendingTransaction).toBeCalledTimes(1)
expect(setPendingConfirmations).toBeCalledTimes(1) expect(setPendingConfirmations).toBeCalledTimes(1)
expect(setPendingConfirmations.mock.calls[0][0]).toEqual(true)
expect(setResult.mock.calls[0][0]()).toEqual( expect(setResult.mock.calls[0][0]()).toEqual(
expect.arrayContaining([ expect.arrayContaining([
@ -498,13 +513,16 @@ describe('getConfirmationsForTx', () => {
expect(setResult).toBeCalledTimes(2) expect(setResult).toBeCalledTimes(2)
expect(getValidatorConfirmation).toBeCalledTimes(1) expect(getValidatorConfirmation).toBeCalledTimes(1)
expect(getValidatorSuccessTransaction).toBeCalledTimes(1) expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
expect(setSignatureCollected).toBeCalledTimes(0) expect(setSignatureCollected).toBeCalledTimes(1)
expect(setSignatureCollected.mock.calls[0][0]).toEqual(false)
expect(getValidatorFailedTransaction).toBeCalledTimes(1) expect(getValidatorFailedTransaction).toBeCalledTimes(1)
expect(setFailedConfirmations).toBeCalledTimes(1) expect(setFailedConfirmations).toBeCalledTimes(1)
expect(setFailedConfirmations.mock.calls[0][0]).toEqual(true)
expect(getValidatorPendingTransaction).toBeCalledTimes(1) expect(getValidatorPendingTransaction).toBeCalledTimes(1)
expect(setPendingConfirmations).toBeCalledTimes(0) expect(setPendingConfirmations).toBeCalledTimes(1)
expect(setPendingConfirmations.mock.calls[0][0]).toEqual(false)
expect(setResult.mock.calls[0][0]()).toEqual( expect(setResult.mock.calls[0][0]()).toEqual(
expect.arrayContaining([ expect.arrayContaining([
@ -521,4 +539,167 @@ describe('getConfirmationsForTx', () => {
]) ])
) )
}) })
test('should remove pending state after transaction mined', async () => {
// Validator1 success
// Validator2 failed
// Validator3 Pending
getValidatorConfirmation
.mockImplementationOnce(() => async (validator: string) => ({
validator,
status:
validator === validator1 ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED
}))
.mockImplementation(() => async (validator: string) => ({
validator,
status:
validator !== validator2 ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED
}))
getValidatorSuccessTransaction
.mockImplementationOnce(() => async (validatorData: BasicConfirmationParam) => ({
validator: validatorData.validator,
status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS,
txHash: validatorData.validator === validator1 ? '0x123' : '',
timestamp: validatorData.validator === validator1 ? 123 : 0
}))
.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({
validator: validatorData.validator,
status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS,
txHash: validatorData.validator !== validator2 ? '0x123' : '',
timestamp: validatorData.validator !== validator2 ? 123 : 0
}))
getValidatorFailedTransaction.mockImplementation(() => async (validatorData: BasicConfirmationParam) => ({
validator: validatorData.validator,
status:
validatorData.validator === validator2
? VALIDATOR_CONFIRMATION_STATUS.FAILED
: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED,
txHash: validatorData.validator === validator2 ? '0x123' : '',
timestamp: validatorData.validator === validator2 ? 123 : 0
}))
getValidatorPendingTransaction
.mockImplementationOnce(() => async (validatorData: BasicConfirmationParam) => ({
validator: validatorData.validator,
status:
validatorData.validator === validator3
? VALIDATOR_CONFIRMATION_STATUS.PENDING
: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED,
txHash: validatorData.validator === validator3 ? '0x123' : '',
timestamp: validatorData.validator === validator3 ? 123 : 0
}))
.mockImplementationOnce(() => async (validatorData: BasicConfirmationParam) => ({
validator: validatorData.validator,
status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED,
txHash: '',
timestamp: 0
}))
const setResult = jest.fn()
const setSignatureCollected = jest.fn()
const setFailedConfirmations = jest.fn()
const setPendingConfirmations = jest.fn()
await getConfirmationsForTx(
messageData,
web3,
validatorList,
bridgeContract,
confirmationContractMethod,
setResult,
requiredSignatures,
setSignatureCollected,
waitingBlocksResolved,
subscriptions,
timestamp,
getFailedTransactions,
setFailedConfirmations,
getPendingTransactions,
setPendingConfirmations,
getSuccessTransactions
)
unsubscribe()
expect(setResult).toBeCalledTimes(2)
expect(getValidatorConfirmation).toBeCalledTimes(1)
expect(getValidatorSuccessTransaction).toBeCalledTimes(1)
expect(setSignatureCollected).toBeCalledTimes(1)
expect(setSignatureCollected.mock.calls[0][0]).toEqual(false)
expect(getValidatorFailedTransaction).toBeCalledTimes(1)
expect(setFailedConfirmations).toBeCalledTimes(1)
expect(setFailedConfirmations.mock.calls[0][0]).toEqual(false)
expect(getValidatorPendingTransaction).toBeCalledTimes(1)
expect(setPendingConfirmations).toBeCalledTimes(1)
expect(setPendingConfirmations.mock.calls[0][0]).toEqual(true)
expect(setResult.mock.calls[0][0]()).toEqual(
expect.arrayContaining([
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
{ validator: validator3, status: VALIDATOR_CONFIRMATION_STATUS.PENDING, txHash: '0x123', timestamp: 123 }
])
)
expect(setResult.mock.calls[1][0]).toEqual(
expect.arrayContaining([
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: '0x123', timestamp: 123 },
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
{ validator: validator3, status: VALIDATOR_CONFIRMATION_STATUS.PENDING, txHash: '0x123', timestamp: 123 }
])
)
await getConfirmationsForTx(
messageData,
web3,
validatorList,
bridgeContract,
confirmationContractMethod,
setResult,
requiredSignatures,
setSignatureCollected,
waitingBlocksResolved,
subscriptions,
timestamp,
getFailedTransactions,
setFailedConfirmations,
getPendingTransactions,
setPendingConfirmations,
getSuccessTransactions
)
unsubscribe()
expect(setResult).toBeCalledTimes(4)
expect(getValidatorConfirmation).toBeCalledTimes(2)
expect(getValidatorSuccessTransaction).toBeCalledTimes(2)
expect(setSignatureCollected).toBeCalledTimes(2)
expect(setSignatureCollected.mock.calls[0][0]).toEqual(false)
expect(setSignatureCollected.mock.calls[1][0]).toEqual(true)
expect(getValidatorFailedTransaction).toBeCalledTimes(2)
expect(setFailedConfirmations).toBeCalledTimes(2)
expect(setFailedConfirmations.mock.calls[0][0]).toEqual(false)
expect(setFailedConfirmations.mock.calls[1][0]).toEqual(false)
expect(getValidatorPendingTransaction).toBeCalledTimes(1)
expect(setPendingConfirmations).toBeCalledTimes(2)
expect(setPendingConfirmations.mock.calls[0][0]).toEqual(true)
expect(setPendingConfirmations.mock.calls[1][0]).toEqual(false)
expect(setResult.mock.calls[2][0]()).toEqual(
expect.arrayContaining([
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS },
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
{ validator: validator3, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS }
])
)
expect(setResult.mock.calls[3][0]).toEqual(
expect.arrayContaining([
{ validator: validator1, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: '0x123', timestamp: 123 },
{ validator: validator2, status: VALIDATOR_CONFIRMATION_STATUS.FAILED, txHash: '0x123', timestamp: 123 },
{ validator: validator3, status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS, txHash: '0x123', timestamp: 123 }
])
)
})
}) })

@ -59,6 +59,7 @@ export const getConfirmationsForTx = async (
const notSuccessConfirmations = validatorConfirmations.filter(c => c.status !== VALIDATOR_CONFIRMATION_STATUS.SUCCESS) const notSuccessConfirmations = validatorConfirmations.filter(c => c.status !== VALIDATOR_CONFIRMATION_STATUS.SUCCESS)
// If signatures not collected, look for pending transactions // If signatures not collected, look for pending transactions
let pendingConfirmationsResult = false
if (successConfirmations.length !== requiredSignatures) { if (successConfirmations.length !== requiredSignatures) {
// Check if confirmation is pending // Check if confirmation is pending
const validatorPendingConfirmationsChecks = await Promise.all( const validatorPendingConfirmationsChecks = await Promise.all(
@ -74,7 +75,7 @@ export const getConfirmationsForTx = async (
}) })
if (validatorPendingConfirmations.length > 0) { if (validatorPendingConfirmations.length > 0) {
setPendingConfirmations(true) pendingConfirmationsResult = true
} }
} }
@ -83,6 +84,7 @@ export const getConfirmationsForTx = async (
) )
// Check if confirmation failed // Check if confirmation failed
let failedConfirmationsResult = false
const validatorFailedConfirmationsChecks = await Promise.all( const validatorFailedConfirmationsChecks = await Promise.all(
undefinedConfirmations.map( undefinedConfirmations.map(
getValidatorFailedTransaction(bridgeContract, messageData, timestamp, getFailedTransactions) getValidatorFailedTransaction(bridgeContract, messageData, timestamp, getFailedTransactions)
@ -97,7 +99,7 @@ export const getConfirmationsForTx = async (
}) })
const messageConfirmationsFailed = validatorFailedConfirmations.length > validatorList.length - requiredSignatures const messageConfirmationsFailed = validatorFailedConfirmations.length > validatorList.length - requiredSignatures
if (messageConfirmationsFailed) { if (messageConfirmationsFailed) {
setFailedConfirmations(true) failedConfirmationsResult = true
} }
const missingConfirmations = validatorConfirmations.filter( const missingConfirmations = validatorConfirmations.filter(
@ -108,6 +110,7 @@ export const getConfirmationsForTx = async (
shouldRetry = true shouldRetry = true
} }
let signatureCollectedResult = false
if (successConfirmations.length === requiredSignatures) { if (successConfirmations.length === requiredSignatures) {
// If signatures collected, it should set other signatures not found as not required // If signatures collected, it should set other signatures not found as not required
const notRequiredConfirmations = missingConfirmations.map(c => ({ const notRequiredConfirmations = missingConfirmations.map(c => ({
@ -116,7 +119,7 @@ export const getConfirmationsForTx = async (
})) }))
validatorConfirmations = [...validatorConfirmations, ...notRequiredConfirmations] validatorConfirmations = [...validatorConfirmations, ...notRequiredConfirmations]
setSignatureCollected(true) signatureCollectedResult = true
} }
// get transactions from success signatures // get transactions from success signatures
@ -137,7 +140,11 @@ export const getConfirmationsForTx = async (
}) })
} }
// Set results
setResult(updatedValidatorConfirmations) setResult(updatedValidatorConfirmations)
setFailedConfirmations(failedConfirmationsResult)
setPendingConfirmations(pendingConfirmationsResult)
setSignatureCollected(signatureCollectedResult)
// Retry if not all transaction were found for validator confirmations // Retry if not all transaction were found for validator confirmations
if (successConfirmationWithTxFound.length < successConfirmationWithData.length) { if (successConfirmationWithTxFound.length < successConfirmationWithData.length) {