Add ALM transaction verification detection (#356)
This commit is contained in:
parent
9b3e6a51a9
commit
3c956ab9ec
@ -23,7 +23,7 @@
|
||||
"react-scripts": "3.0.1",
|
||||
"styled-components": "^5.1.1",
|
||||
"typescript": "^3.5.2",
|
||||
"web3": "^1.2.8"
|
||||
"web3": "1.2.7"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "./load-env.sh react-app-rewired start",
|
||||
|
@ -25,7 +25,7 @@
|
||||
work correctly both with client-side routing and a non-root public URL.
|
||||
Learn how to configure a non-root public URL by running `npm run build`.
|
||||
-->
|
||||
<title>React App</title>
|
||||
<title>AMB Live Monitoring</title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||
|
@ -1,9 +1,5 @@
|
||||
import React from 'react'
|
||||
import { render } from '@testing-library/react'
|
||||
import App from './App'
|
||||
|
||||
test('renders learn react link', () => {
|
||||
const { getByText } = render(<App />)
|
||||
const linkElement = getByText(/AMB Live Monitoring/i)
|
||||
expect(linkElement).toBeInTheDocument()
|
||||
// Removed basic test from setup. Keeping this so CI passes until we add unit tests.
|
||||
})
|
||||
|
72
alm/src/components/ConfirmationsContainer.tsx
Normal file
72
alm/src/components/ConfirmationsContainer.tsx
Normal file
@ -0,0 +1,72 @@
|
||||
import React from 'react'
|
||||
import { TransactionReceipt } from 'web3-eth'
|
||||
import { useMessageConfirmations } from '../hooks/useMessageConfirmations'
|
||||
import { MessageObject } from '../utils/web3'
|
||||
import styled from 'styled-components'
|
||||
import { CONFIRMATIONS_STATUS } from '../config/constants'
|
||||
import { CONFIRMATIONS_STATUS_LABEL } from '../config/descriptions'
|
||||
import { SimpleLoading } from './commons/Loading'
|
||||
import { ValidatorsConfirmations } from './ValidatorsConfirmations'
|
||||
import { getConfirmationsStatusDescription } from '../utils/networks'
|
||||
import { useStateProvider } from '../state/StateProvider'
|
||||
import { ExecutionConfirmation } from './ExecutionConfirmation'
|
||||
|
||||
const StatusLabel = styled.label`
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
`
|
||||
|
||||
const StatusResultLabel = styled.label`
|
||||
font-size: 18px;
|
||||
padding-left: 10px;
|
||||
`
|
||||
|
||||
const StyledConfirmationContainer = styled.div`
|
||||
background-color: var(--color-primary);
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
`
|
||||
|
||||
const StatusDescription = styled.div`
|
||||
padding-top: 10px;
|
||||
`
|
||||
|
||||
export interface ConfirmationsContainerParams {
|
||||
message: MessageObject
|
||||
receipt: Maybe<TransactionReceipt>
|
||||
fromHome: boolean
|
||||
}
|
||||
|
||||
export const ConfirmationsContainer = ({ message, receipt, fromHome }: ConfirmationsContainerParams) => {
|
||||
const {
|
||||
home: { name: homeName },
|
||||
foreign: { name: foreignName }
|
||||
} = useStateProvider()
|
||||
const { confirmations, status, executionData, signatureCollected } = useMessageConfirmations({
|
||||
message,
|
||||
receipt,
|
||||
fromHome
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="row is-center">
|
||||
<StyledConfirmationContainer className="col-9">
|
||||
<div className="row is-center">
|
||||
<StatusLabel>Status:</StatusLabel>
|
||||
<StatusResultLabel>
|
||||
{status !== CONFIRMATIONS_STATUS.UNDEFINED ? CONFIRMATIONS_STATUS_LABEL[status] : <SimpleLoading />}
|
||||
</StatusResultLabel>
|
||||
</div>
|
||||
<StatusDescription className="row is-center">
|
||||
<p className="col-10">
|
||||
{status !== CONFIRMATIONS_STATUS.UNDEFINED
|
||||
? getConfirmationsStatusDescription(status, homeName, foreignName)
|
||||
: ''}
|
||||
</p>
|
||||
</StatusDescription>
|
||||
<ValidatorsConfirmations confirmations={confirmations} />
|
||||
{signatureCollected && <ExecutionConfirmation executionData={executionData} isHome={!fromHome} />}
|
||||
</StyledConfirmationContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
66
alm/src/components/ExecutionConfirmation.tsx
Normal file
66
alm/src/components/ExecutionConfirmation.tsx
Normal file
@ -0,0 +1,66 @@
|
||||
import React from 'react'
|
||||
import { formatTimestamp, formatTxHash, getExplorerTxUrl } from '../utils/networks'
|
||||
import { useWindowWidth } from '@react-hook/window-size'
|
||||
import { VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
||||
import { SimpleLoading } from './commons/Loading'
|
||||
import styled from 'styled-components'
|
||||
import { ExecutionData } from '../hooks/useMessageConfirmations'
|
||||
import { GreyLabel, SuccessLabel } from './commons/Labels'
|
||||
import { ExplorerTxLink } from './commons/ExplorerTxLink'
|
||||
|
||||
const Thead = styled.thead`
|
||||
border-bottom: 2px solid #9e9e9e;
|
||||
`
|
||||
|
||||
const StyledExecutionConfirmation = styled.div`
|
||||
margin-top: 30px;
|
||||
`
|
||||
|
||||
export interface ExecutionConfirmationParams {
|
||||
executionData: ExecutionData
|
||||
isHome: boolean
|
||||
}
|
||||
|
||||
export const ExecutionConfirmation = ({ executionData, isHome }: ExecutionConfirmationParams) => {
|
||||
const windowWidth = useWindowWidth()
|
||||
|
||||
const txExplorerLink = getExplorerTxUrl(executionData.txHash, isHome)
|
||||
const formattedValidator =
|
||||
windowWidth < 850 && executionData.validator ? formatTxHash(executionData.validator) : executionData.validator
|
||||
|
||||
const getExecutionStatusElement = (validatorStatus = '') => {
|
||||
switch (validatorStatus) {
|
||||
case VALIDATOR_CONFIRMATION_STATUS.SUCCESS:
|
||||
return <SuccessLabel>{validatorStatus}</SuccessLabel>
|
||||
case VALIDATOR_CONFIRMATION_STATUS.WAITING:
|
||||
return <GreyLabel>{validatorStatus}</GreyLabel>
|
||||
default:
|
||||
return <SimpleLoading />
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledExecutionConfirmation>
|
||||
<table>
|
||||
<Thead>
|
||||
<tr>
|
||||
<th>Executed by</th>
|
||||
<th className="text-center">Status</th>
|
||||
<th className="text-center">Age</th>
|
||||
</tr>
|
||||
</Thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{formattedValidator ? formattedValidator : <SimpleLoading />}</td>
|
||||
<td className="text-center">{getExecutionStatusElement(executionData.status)}</td>
|
||||
<td className="text-center">
|
||||
<ExplorerTxLink href={txExplorerLink} target="blank">
|
||||
{executionData.timestamp > 0 ? formatTimestamp(executionData.timestamp) : ''}
|
||||
</ExplorerTxLink>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</StyledExecutionConfirmation>
|
||||
)
|
||||
}
|
@ -14,6 +14,7 @@ const LabelText = styled.label`
|
||||
const Input = styled.input`
|
||||
background-color: var(--color-primary);
|
||||
color: var(--font-color);
|
||||
max-width: 100%;
|
||||
`
|
||||
|
||||
export const Form = ({ onSubmit }: { onSubmit: ({ chainId, txHash }: FormSubmitParams) => void }) => {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { Route, useHistory } from 'react-router-dom'
|
||||
import { Route, useHistory, Link } from 'react-router-dom'
|
||||
import { Form } from './Form'
|
||||
import { StatusContainer } from './StatusContainer'
|
||||
import { StateProvider } from '../state/StateProvider'
|
||||
@ -18,6 +18,10 @@ const Header = styled.header`
|
||||
font-size: calc(10px + 2vmin);
|
||||
`
|
||||
|
||||
const Title = styled.p`
|
||||
color: var(--font-color);
|
||||
`
|
||||
|
||||
export interface FormSubmitParams {
|
||||
chainId: number
|
||||
txHash: string
|
||||
@ -33,13 +37,12 @@ export const MainPage = () => {
|
||||
<StateProvider>
|
||||
<StyledMainPage>
|
||||
<Header>
|
||||
<p>AMB Live Monitoring</p>
|
||||
<Link to="/">
|
||||
<Title>AMB Live Monitoring</Title>
|
||||
</Link>
|
||||
</Header>
|
||||
<div className="container">
|
||||
<Route
|
||||
path={['/:chainId/:txHash/:messageIdParam', '/:chainId/:txHash', '/']}
|
||||
children={<Form onSubmit={onFormSubmit} />}
|
||||
/>
|
||||
<Route exact path={['/']} children={<Form onSubmit={onFormSubmit} />} />
|
||||
<Route path={['/:chainId/:txHash/:messageIdParam', '/:chainId/:txHash']} children={<StatusContainer />} />
|
||||
</div>
|
||||
</StyledMainPage>
|
||||
|
@ -3,9 +3,10 @@ import { Button } from './commons/Button'
|
||||
import { RadioButtonLabel, RadioButtonContainer } from './commons/RadioButton'
|
||||
import { useWindowWidth } from '@react-hook/window-size'
|
||||
import { formatTxHashExtended } from '../utils/networks'
|
||||
import { MessageObject } from '../utils/web3'
|
||||
|
||||
export interface MessageSelectorParams {
|
||||
messages: Array<string>
|
||||
messages: Array<MessageObject>
|
||||
onMessageSelected: (index: number) => void
|
||||
}
|
||||
|
||||
@ -31,7 +32,7 @@ export const MessageSelector = ({ messages, onMessageSelected }: MessageSelector
|
||||
onChange={() => setMessageIndex(i)}
|
||||
/>
|
||||
<RadioButtonLabel htmlFor={i.toString()}>
|
||||
{windowWidth < 700 ? formatTxHashExtended(message) : message}
|
||||
{windowWidth < 700 ? formatTxHashExtended(message.id) : message.id}
|
||||
</RadioButtonLabel>
|
||||
</RadioButtonContainer>
|
||||
))}
|
||||
|
@ -7,6 +7,7 @@ import { MessageSelector } from './MessageSelector'
|
||||
import { Loading } from './commons/Loading'
|
||||
import { useStateProvider } from '../state/StateProvider'
|
||||
import { ExplorerTxLink } from './commons/ExplorerTxLink'
|
||||
import { ConfirmationsContainer } from './ConfirmationsContainer'
|
||||
|
||||
export const StatusContainer = () => {
|
||||
const { home, foreign } = useStateProvider()
|
||||
@ -15,15 +16,14 @@ export const StatusContainer = () => {
|
||||
const validChainId = chainId === home.chainId.toString() || chainId === foreign.chainId.toString()
|
||||
const validParameters = validChainId && validTxHash(txHash)
|
||||
|
||||
const { messagesId, status, description, timestamp, loading } = useTransactionStatus({
|
||||
const { messages, receipt, status, description, timestamp, loading } = useTransactionStatus({
|
||||
txHash: validParameters ? txHash : '',
|
||||
chainId: validParameters ? parseInt(chainId) : 0
|
||||
})
|
||||
|
||||
const selectedMessageId =
|
||||
messageIdParam === undefined || messagesId[messageIdParam] === undefined ? -1 : messageIdParam
|
||||
const selectedMessageId = messageIdParam === undefined || messages[messageIdParam] === undefined ? -1 : messageIdParam
|
||||
|
||||
if (!validParameters) {
|
||||
if (!validParameters && home.chainId && foreign.chainId) {
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
@ -43,7 +43,7 @@ export const StatusContainer = () => {
|
||||
|
||||
const displayMessageSelector = status === TRANSACTION_STATUS.SUCCESS_MULTIPLE_MESSAGES && selectedMessageId === -1
|
||||
const multiMessageSelected = status === TRANSACTION_STATUS.SUCCESS_MULTIPLE_MESSAGES && selectedMessageId !== -1
|
||||
const displayReference = multiMessageSelected ? messagesId[selectedMessageId] : txHash
|
||||
const displayReference = multiMessageSelected ? messages[selectedMessageId].id : txHash
|
||||
const formattedMessageId = formatTxHash(displayReference)
|
||||
|
||||
const displayedDescription = multiMessageSelected
|
||||
@ -54,6 +54,9 @@ export const StatusContainer = () => {
|
||||
const txExplorerLink = getExplorerTxUrl(txHash, isHome)
|
||||
const displayExplorerLink = status !== TRANSACTION_STATUS.NOT_FOUND
|
||||
|
||||
const displayConfirmations = status === TRANSACTION_STATUS.SUCCESS_ONE_MESSAGE || multiMessageSelected
|
||||
const messageToConfirm =
|
||||
messages.length > 1 ? messages[selectedMessageId] : messages.length > 0 ? messages[0] : { id: '', data: '' }
|
||||
return (
|
||||
<div>
|
||||
{status && (
|
||||
@ -70,7 +73,10 @@ export const StatusContainer = () => {
|
||||
{displayedDescription}
|
||||
</p>
|
||||
)}
|
||||
{displayMessageSelector && <MessageSelector messages={messagesId} onMessageSelected={onMessageSelected} />}
|
||||
{displayMessageSelector && <MessageSelector messages={messages} onMessageSelected={onMessageSelected} />}
|
||||
{displayConfirmations && (
|
||||
<ConfirmationsContainer message={messageToConfirm} receipt={receipt} fromHome={isHome} />
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
69
alm/src/components/ValidatorsConfirmations.tsx
Normal file
69
alm/src/components/ValidatorsConfirmations.tsx
Normal file
@ -0,0 +1,69 @@
|
||||
import React from 'react'
|
||||
import { formatTxHashExtended } from '../utils/networks'
|
||||
import { useStateProvider } from '../state/StateProvider'
|
||||
import { useWindowWidth } from '@react-hook/window-size'
|
||||
import { VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
||||
import { SimpleLoading } from './commons/Loading'
|
||||
import styled from 'styled-components'
|
||||
import { ConfirmationParam } from '../hooks/useMessageConfirmations'
|
||||
import { GreyLabel, SuccessLabel } from './commons/Labels'
|
||||
|
||||
const Thead = styled.thead`
|
||||
border-bottom: 2px solid #9e9e9e;
|
||||
`
|
||||
|
||||
const RequiredConfirmations = styled.label`
|
||||
font-size: 14px;
|
||||
`
|
||||
|
||||
export interface ValidatorsConfirmationsParams {
|
||||
confirmations: Array<ConfirmationParam>
|
||||
}
|
||||
|
||||
export const ValidatorsConfirmations = ({ confirmations }: ValidatorsConfirmationsParams) => {
|
||||
const {
|
||||
home: { requiredSignatures, validatorList }
|
||||
} = useStateProvider()
|
||||
const windowWidth = useWindowWidth()
|
||||
|
||||
const getValidatorStatusElement = (validatorStatus = '') => {
|
||||
switch (validatorStatus) {
|
||||
case VALIDATOR_CONFIRMATION_STATUS.SUCCESS:
|
||||
return <SuccessLabel>{validatorStatus}</SuccessLabel>
|
||||
case VALIDATOR_CONFIRMATION_STATUS.WAITING:
|
||||
case VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED:
|
||||
return <GreyLabel>{validatorStatus}</GreyLabel>
|
||||
default:
|
||||
return <SimpleLoading />
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<table>
|
||||
<Thead>
|
||||
<tr>
|
||||
<th>Validator</th>
|
||||
<th className="is-center">Confirmations</th>
|
||||
</tr>
|
||||
</Thead>
|
||||
<tbody>
|
||||
{validatorList.map((validator, i) => {
|
||||
const filteredConfirmation = confirmations.filter(c => c.validator === validator)
|
||||
const confirmation = filteredConfirmation.length > 0 ? filteredConfirmation[0] : null
|
||||
const displayedStatus = confirmation && confirmation.status ? confirmation.status : ''
|
||||
return (
|
||||
<tr key={i}>
|
||||
<td>{windowWidth < 850 ? formatTxHashExtended(validator) : validator}</td>
|
||||
<td className="text-center">{getValidatorStatusElement(displayedStatus)}</td>
|
||||
</tr>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<RequiredConfirmations>
|
||||
{requiredSignatures} of {validatorList.length} confirmations required
|
||||
</RequiredConfirmations>
|
||||
</div>
|
||||
)
|
||||
}
|
15
alm/src/components/commons/Labels.tsx
Normal file
15
alm/src/components/commons/Labels.tsx
Normal file
@ -0,0 +1,15 @@
|
||||
import styled from 'styled-components'
|
||||
|
||||
export const SuccessLabel = styled.label`
|
||||
color: var(--success-color);
|
||||
background-color: var(--success-bg-color);
|
||||
padding: 0.4rem 0.7rem;
|
||||
border-radius: 4px;
|
||||
`
|
||||
|
||||
export const GreyLabel = styled.label`
|
||||
color: var(--not-required-color);
|
||||
background-color: var(--not-required-bg-color);
|
||||
padding: 0.4rem 0.7rem;
|
||||
border-radius: 4px;
|
||||
`
|
@ -1,12 +1,18 @@
|
||||
import React from 'react'
|
||||
|
||||
export const Loading = () => (
|
||||
export interface LoadingParams {
|
||||
width?: string
|
||||
height?: string
|
||||
displayMessage?: boolean
|
||||
}
|
||||
|
||||
export const Loading = ({ width = '50px', height = '50px', displayMessage = true }: LoadingParams) => (
|
||||
<div className="row is-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style={{ background: 'none', display: 'block', shapeRendering: 'auto' }}
|
||||
width="50px"
|
||||
height="50px"
|
||||
width={width}
|
||||
height={height}
|
||||
viewBox="0 0 100 100"
|
||||
preserveAspectRatio="xMidYMid"
|
||||
>
|
||||
@ -148,6 +154,8 @@ export const Loading = () => (
|
||||
</rect>
|
||||
</g>
|
||||
</svg>
|
||||
<label>Loading...</label>
|
||||
{displayMessage && <label>Loading...</label>}
|
||||
</div>
|
||||
)
|
||||
|
||||
export const SimpleLoading = () => <Loading width="30px" height="30px" displayMessage={false} />
|
||||
|
@ -10,6 +10,10 @@ export const FOREIGN_NETWORK_NAME: string = process.env.REACT_APP_ALM_FOREIGN_NE
|
||||
export const HOME_EXPLORER_TX_TEMPLATE: string = process.env.REACT_APP_ALM_HOME_EXPLORER_TX_TEMPLATE || ''
|
||||
export const FOREIGN_EXPLORER_TX_TEMPLATE: string = process.env.REACT_APP_ALM_FOREIGN_EXPLORER_TX_TEMPLATE || ''
|
||||
|
||||
export const HOME_RPC_POLLING_INTERVAL: number = 5000
|
||||
export const FOREIGN_RPC_POLLING_INTERVAL: number = 15000
|
||||
export const BLOCK_RANGE: number = 50
|
||||
|
||||
export const TRANSACTION_STATUS = {
|
||||
SUCCESS_MULTIPLE_MESSAGES: 'SUCCESS_MULTIPLE_MESSAGES',
|
||||
SUCCESS_ONE_MESSAGE: 'SUCCESS_ONE_MESSAGE',
|
||||
@ -17,3 +21,24 @@ export const TRANSACTION_STATUS = {
|
||||
FAILED: 'FAILED',
|
||||
NOT_FOUND: 'NOT_FOUND'
|
||||
}
|
||||
|
||||
export const CONFIRMATIONS_STATUS = {
|
||||
SUCCESS: 'SUCCESS',
|
||||
SUCCESS_MESSAGE_FAILED: 'SUCCESS_MESSAGE_FAILED',
|
||||
EXECUTION_FAILED: 'EXECUTION_FAILED',
|
||||
EXECUTION_PENDING: 'EXECUTION_PENDING',
|
||||
EXECUTION_WAITING: 'EXECUTION_WAITING',
|
||||
FAILED: 'FAILED',
|
||||
PENDING: 'PENDING',
|
||||
WAITING: 'WAITING',
|
||||
UNDEFINED: 'UNDEFINED'
|
||||
}
|
||||
|
||||
export const VALIDATOR_CONFIRMATION_STATUS = {
|
||||
SUCCESS: 'Success',
|
||||
FAILED: 'Failed',
|
||||
PENDING: 'Pending',
|
||||
WAITING: 'Waiting',
|
||||
NOT_REQUIRED: 'Not required',
|
||||
UNDEFINED: 'UNDEFINED'
|
||||
}
|
||||
|
@ -6,3 +6,31 @@ export const TRANSACTION_STATUS_DESCRIPTION: { [key: string]: string } = {
|
||||
FAILED: 'failed %t',
|
||||
NOT_FOUND: 'was not found'
|
||||
}
|
||||
|
||||
export const CONFIRMATIONS_STATUS_LABEL: { [key: string]: string } = {
|
||||
SUCCESS: 'Success',
|
||||
SUCCESS_MESSAGE_FAILED: 'Success',
|
||||
EXECUTION_FAILED: 'Execution failed',
|
||||
EXECUTION_PENDING: 'Execution pending',
|
||||
EXECUTION_WAITING: 'Execution waiting',
|
||||
FAILED: 'Failed',
|
||||
PENDING: 'Pending',
|
||||
WAITING: 'Waiting'
|
||||
}
|
||||
|
||||
// %homeChain will be replaced by the home network name
|
||||
// %foreignChain will be replaced by the foreign network name
|
||||
export const CONFIRMATIONS_STATUS_DESCRIPTION: { [key: string]: string } = {
|
||||
SUCCESS: '',
|
||||
SUCCESS_MESSAGE_FAILED:
|
||||
'Signatures have been collected in the %homeChain and they were successfully sent to the %foreignChain but the contained message execution failed.',
|
||||
EXECUTION_FAILED:
|
||||
'Signatures have been collected in the %homeChain and they were sent to the %foreignChain but the transaction with signatures failed',
|
||||
EXECUTION_PENDING:
|
||||
'Signatures have been collected in the %homeChain and they were sent to the %foreignChain but the transaction is in the pending state (transactions congestion or low gas price)',
|
||||
EXECUTION_WAITING: 'Execution waiting',
|
||||
FAILED:
|
||||
'Some validators sent improper transactions as so they were failed, collected confirmations are not enough to execute the relay request',
|
||||
PENDING: 'Some confirmations are in pending state',
|
||||
WAITING: 'Validators are waiting for the chain finalization'
|
||||
}
|
||||
|
90
alm/src/hooks/useBridgeContracts.ts
Normal file
90
alm/src/hooks/useBridgeContracts.ts
Normal file
@ -0,0 +1,90 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { HOME_AMB_ABI, FOREIGN_AMB_ABI, BRIDGE_VALIDATORS_ABI } from '../../../commons'
|
||||
import { FOREIGN_BRIDGE_ADDRESS, HOME_BRIDGE_ADDRESS } from '../config/constants'
|
||||
import { Contract } from 'web3-eth-contract'
|
||||
import Web3 from 'web3'
|
||||
import {
|
||||
getRequiredBlockConfirmations,
|
||||
getRequiredSignatures,
|
||||
getValidatorAddress,
|
||||
getValidatorList
|
||||
} from '../utils/contract'
|
||||
|
||||
export interface useBridgeContractsParams {
|
||||
homeWeb3: Web3
|
||||
foreignWeb3: Web3
|
||||
}
|
||||
|
||||
export const useBridgeContracts = ({ homeWeb3, foreignWeb3 }: useBridgeContractsParams) => {
|
||||
const [homeBridge, setHomeBridge] = useState<Maybe<Contract>>(null)
|
||||
const [foreignBridge, setForeignBridge] = useState<Maybe<Contract>>(null)
|
||||
const [homeBlockConfirmations, setHomeBlockConfirmations] = useState(0)
|
||||
const [foreignBlockConfirmations, setForeignBlockConfirmations] = useState(0)
|
||||
const [homeValidatorContract, setHomeValidatorContract] = useState<Maybe<Contract>>(null)
|
||||
const [homeRequiredSignatures, setHomeRequiredSignatures] = useState(0)
|
||||
const [homeValidatorList, setHomeValidatorList] = useState([])
|
||||
|
||||
const callRequireBlockConfirmations = async (contract: Maybe<Contract>, setResult: Function) => {
|
||||
if (!contract) return
|
||||
const result = await getRequiredBlockConfirmations(contract)
|
||||
setResult(result)
|
||||
}
|
||||
|
||||
const callValidatorContract = async (bridgeContract: Maybe<Contract>, web3: Web3, setValidatorContract: Function) => {
|
||||
if (!web3 || !bridgeContract) return
|
||||
const address = await getValidatorAddress(bridgeContract)
|
||||
const contract = new web3.eth.Contract(BRIDGE_VALIDATORS_ABI, address)
|
||||
setValidatorContract(contract)
|
||||
}
|
||||
|
||||
const callRequiredSignatures = async (contract: Maybe<Contract>, setResult: Function) => {
|
||||
if (!contract) return
|
||||
const result = await getRequiredSignatures(contract)
|
||||
setResult(result)
|
||||
}
|
||||
|
||||
const callValidatorList = async (contract: Maybe<Contract>, setResult: Function) => {
|
||||
if (!contract) return
|
||||
const result = await getValidatorList(contract)
|
||||
setResult(result)
|
||||
}
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (!homeWeb3) return
|
||||
const homeContract = new homeWeb3.eth.Contract(HOME_AMB_ABI, HOME_BRIDGE_ADDRESS)
|
||||
callRequireBlockConfirmations(homeContract, setHomeBlockConfirmations)
|
||||
callValidatorContract(homeContract, homeWeb3, setHomeValidatorContract)
|
||||
setHomeBridge(homeContract)
|
||||
},
|
||||
[homeWeb3]
|
||||
)
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
if (!foreignWeb3) return
|
||||
const foreignContract = new foreignWeb3.eth.Contract(FOREIGN_AMB_ABI, FOREIGN_BRIDGE_ADDRESS)
|
||||
callRequireBlockConfirmations(foreignContract, setForeignBlockConfirmations)
|
||||
setForeignBridge(foreignContract)
|
||||
},
|
||||
[foreignWeb3]
|
||||
)
|
||||
|
||||
useEffect(
|
||||
() => {
|
||||
callRequiredSignatures(homeValidatorContract, setHomeRequiredSignatures)
|
||||
callValidatorList(homeValidatorContract, setHomeValidatorList)
|
||||
},
|
||||
[homeValidatorContract]
|
||||
)
|
||||
|
||||
return {
|
||||
homeBridge,
|
||||
foreignBridge,
|
||||
homeBlockConfirmations,
|
||||
foreignBlockConfirmations,
|
||||
homeValidatorContract,
|
||||
homeRequiredSignatures,
|
||||
homeValidatorList
|
||||
}
|
||||
}
|
305
alm/src/hooks/useMessageConfirmations.ts
Normal file
305
alm/src/hooks/useMessageConfirmations.ts
Normal file
@ -0,0 +1,305 @@
|
||||
import { useStateProvider } from '../state/StateProvider'
|
||||
import { TransactionReceipt } from 'web3-eth'
|
||||
import { MessageObject } from '../utils/web3'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { EventData } from 'web3-eth-contract'
|
||||
import { getAffirmationsSigned, getMessagesSigned } from '../utils/contract'
|
||||
import {
|
||||
BLOCK_RANGE,
|
||||
CONFIRMATIONS_STATUS,
|
||||
FOREIGN_RPC_POLLING_INTERVAL,
|
||||
HOME_RPC_POLLING_INTERVAL,
|
||||
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'
|
||||
|
||||
export interface useMessageConfirmationsParams {
|
||||
message: MessageObject
|
||||
receipt: Maybe<TransactionReceipt>
|
||||
fromHome: boolean
|
||||
}
|
||||
|
||||
export interface ConfirmationParam {
|
||||
validator: string
|
||||
status: string
|
||||
}
|
||||
|
||||
export interface ExecutionData {
|
||||
status: string
|
||||
validator: string
|
||||
txHash: string
|
||||
timestamp: number
|
||||
executionResult: boolean
|
||||
}
|
||||
|
||||
export const useMessageConfirmations = ({ message, receipt, fromHome }: useMessageConfirmationsParams) => {
|
||||
const { home, foreign } = useStateProvider()
|
||||
const [confirmations, setConfirmations] = useState<Array<ConfirmationParam>>([])
|
||||
const [status, setStatus] = useState(CONFIRMATIONS_STATUS.UNDEFINED)
|
||||
const [waitingBlocks, setWaitingBlocks] = useState(false)
|
||||
const [waitingBlocksResolved, setWaitingBlocksResolved] = useState(false)
|
||||
const [signatureCollected, setSignatureCollected] = useState(false)
|
||||
const [collectedSignaturesEvent, setCollectedSignaturesEvent] = useState<Maybe<EventData>>(null)
|
||||
const [executionData, setExecutionData] = useState<ExecutionData>({
|
||||
status: VALIDATOR_CONFIRMATION_STATUS.UNDEFINED,
|
||||
validator: '',
|
||||
txHash: '',
|
||||
timestamp: 0,
|
||||
executionResult: false
|
||||
})
|
||||
const [waitingBlocksForExecution, setWaitingBlocksForExecution] = useState(false)
|
||||
const [waitingBlocksForExecutionResolved, setWaitingBlocksForExecutionResolved] = useState(false)
|
||||
|
||||
// Check if the validators are waiting for block confirmations to verify the message
|
||||
useEffect(
|
||||
() => {
|
||||
if (!receipt) return
|
||||
|
||||
const subscriptions: Array<number> = []
|
||||
|
||||
const unsubscribe = () => {
|
||||
subscriptions.forEach(s => {
|
||||
clearTimeout(s)
|
||||
})
|
||||
}
|
||||
|
||||
const blockProvider = fromHome ? homeBlockNumberProvider : foreignBlockNumberProvider
|
||||
const interval = fromHome ? HOME_RPC_POLLING_INTERVAL : FOREIGN_RPC_POLLING_INTERVAL
|
||||
const web3 = fromHome ? home.web3 : foreign.web3
|
||||
blockProvider.start(web3)
|
||||
|
||||
const requiredBlockConfirmations = fromHome ? home.blockConfirmations : foreign.blockConfirmations
|
||||
const targetBlock = receipt.blockNumber + requiredBlockConfirmations
|
||||
|
||||
checkSignaturesWaitingForBLocks(
|
||||
targetBlock,
|
||||
setWaitingBlocks,
|
||||
setWaitingBlocksResolved,
|
||||
home.validatorList,
|
||||
setConfirmations,
|
||||
blockProvider,
|
||||
interval,
|
||||
subscriptions
|
||||
)
|
||||
|
||||
return () => {
|
||||
unsubscribe()
|
||||
blockProvider.stop()
|
||||
}
|
||||
},
|
||||
[
|
||||
foreign.blockConfirmations,
|
||||
foreign.web3,
|
||||
fromHome,
|
||||
home.blockConfirmations,
|
||||
home.validatorList,
|
||||
home.web3,
|
||||
receipt
|
||||
]
|
||||
)
|
||||
|
||||
// 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
|
||||
useEffect(
|
||||
() => {
|
||||
if (!fromHome || !receipt || !home.web3 || !signatureCollected) return
|
||||
|
||||
const subscriptions: Array<number> = []
|
||||
|
||||
const unsubscribe = () => {
|
||||
subscriptions.forEach(s => {
|
||||
clearTimeout(s)
|
||||
})
|
||||
}
|
||||
|
||||
homeBlockNumberProvider.start(home.web3)
|
||||
|
||||
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
|
||||
)
|
||||
|
||||
return () => {
|
||||
unsubscribe()
|
||||
homeBlockNumberProvider.stop()
|
||||
}
|
||||
},
|
||||
[fromHome, home.bridgeContract, home.web3, message.data, receipt, signatureCollected]
|
||||
)
|
||||
|
||||
// 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) return
|
||||
|
||||
const subscriptions: Array<number> = []
|
||||
|
||||
const unsubscribe = () => {
|
||||
subscriptions.forEach(s => {
|
||||
clearTimeout(s)
|
||||
})
|
||||
}
|
||||
|
||||
homeBlockNumberProvider.start(home.web3)
|
||||
const targetBlock = collectedSignaturesEvent.blockNumber + home.blockConfirmations
|
||||
|
||||
checkWaitingBlocksForExecution(
|
||||
homeBlockNumberProvider,
|
||||
HOME_RPC_POLLING_INTERVAL,
|
||||
targetBlock,
|
||||
collectedSignaturesEvent,
|
||||
setWaitingBlocksForExecution,
|
||||
setWaitingBlocksForExecutionResolved,
|
||||
setExecutionData,
|
||||
subscriptions
|
||||
)
|
||||
|
||||
return () => {
|
||||
unsubscribe()
|
||||
homeBlockNumberProvider.stop()
|
||||
}
|
||||
},
|
||||
[collectedSignaturesEvent, fromHome, home.blockConfirmations, home.web3, receipt]
|
||||
)
|
||||
|
||||
// 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) return
|
||||
|
||||
const subscriptions: Array<number> = []
|
||||
|
||||
const unsubscribe = () => {
|
||||
subscriptions.forEach(s => {
|
||||
clearTimeout(s)
|
||||
})
|
||||
}
|
||||
|
||||
const confirmationContractMethod = fromHome ? getMessagesSigned : getAffirmationsSigned
|
||||
|
||||
getConfirmationsForTx(
|
||||
message.data,
|
||||
home.web3,
|
||||
home.validatorList,
|
||||
home.bridgeContract,
|
||||
confirmationContractMethod,
|
||||
setConfirmations,
|
||||
home.requiredSignatures,
|
||||
setSignatureCollected,
|
||||
waitingBlocksResolved,
|
||||
subscriptions
|
||||
)
|
||||
|
||||
return () => {
|
||||
unsubscribe()
|
||||
}
|
||||
},
|
||||
[
|
||||
fromHome,
|
||||
message.data,
|
||||
home.web3,
|
||||
home.validatorList,
|
||||
home.bridgeContract,
|
||||
home.requiredSignatures,
|
||||
waitingBlocksResolved
|
||||
]
|
||||
)
|
||||
|
||||
// Gets finalization event to display the information about the execution of the message
|
||||
// In a message from Home to Foreign it will be executed after finishing waiting for block confirmations for the execution transaction on Foreign
|
||||
// In a message from Foreign to Home it will be executed after finishing waiting for block confirmations of the message request
|
||||
useEffect(
|
||||
() => {
|
||||
if ((fromHome && !waitingBlocksForExecutionResolved) || (!fromHome && !waitingBlocksResolved)) return
|
||||
|
||||
const subscriptions: Array<number> = []
|
||||
|
||||
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
|
||||
|
||||
getFinalizationEvent(
|
||||
bridgeContract,
|
||||
contractEvent,
|
||||
providedWeb3,
|
||||
setExecutionData,
|
||||
waitingBlocksResolved,
|
||||
message.id,
|
||||
interval,
|
||||
subscriptions
|
||||
)
|
||||
|
||||
return () => {
|
||||
unsubscribe()
|
||||
}
|
||||
},
|
||||
[
|
||||
fromHome,
|
||||
foreign.bridgeContract,
|
||||
home.bridgeContract,
|
||||
message.id,
|
||||
foreign.web3,
|
||||
home.web3,
|
||||
waitingBlocksResolved,
|
||||
waitingBlocksForExecutionResolved
|
||||
]
|
||||
)
|
||||
|
||||
// Sets the message status based in the collected information
|
||||
useEffect(
|
||||
() => {
|
||||
if (executionData.txHash) {
|
||||
const newStatus = executionData.executionResult
|
||||
? CONFIRMATIONS_STATUS.SUCCESS
|
||||
: CONFIRMATIONS_STATUS.SUCCESS_MESSAGE_FAILED
|
||||
setStatus(newStatus)
|
||||
} else if (signatureCollected) {
|
||||
if (fromHome) {
|
||||
if (waitingBlocksForExecution) {
|
||||
setStatus(CONFIRMATIONS_STATUS.EXECUTION_WAITING)
|
||||
} else {
|
||||
setStatus(CONFIRMATIONS_STATUS.UNDEFINED)
|
||||
}
|
||||
} else {
|
||||
setStatus(CONFIRMATIONS_STATUS.UNDEFINED)
|
||||
}
|
||||
} else if (waitingBlocks) {
|
||||
setStatus(CONFIRMATIONS_STATUS.WAITING)
|
||||
} else {
|
||||
setStatus(CONFIRMATIONS_STATUS.UNDEFINED)
|
||||
}
|
||||
},
|
||||
[executionData, fromHome, signatureCollected, waitingBlocks, waitingBlocksForExecution]
|
||||
)
|
||||
|
||||
return {
|
||||
confirmations,
|
||||
status,
|
||||
signatureCollected,
|
||||
executionData
|
||||
}
|
||||
}
|
@ -1,13 +1,13 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { TransactionReceipt } from 'web3-eth'
|
||||
import { TRANSACTION_STATUS } from '../config/constants'
|
||||
import { HOME_RPC_POLLING_INTERVAL, TRANSACTION_STATUS } from '../config/constants'
|
||||
import { getTransactionStatusDescription } from '../utils/networks'
|
||||
import { useStateProvider } from '../state/StateProvider'
|
||||
import { getHomeMessagesFromReceipt, getForeignMessagesFromReceipt } from '../utils/web3'
|
||||
import { getHomeMessagesFromReceipt, getForeignMessagesFromReceipt, MessageObject } from '../utils/web3'
|
||||
|
||||
export const useTransactionStatus = ({ txHash, chainId }: { txHash: string; chainId: number }) => {
|
||||
const { home, foreign } = useStateProvider()
|
||||
const [messagesId, setMessagesId] = useState<Array<string>>([])
|
||||
const [messages, setMessages] = useState<Array<MessageObject>>([])
|
||||
const [status, setStatus] = useState('')
|
||||
const [description, setDescription] = useState('')
|
||||
const [receipt, setReceipt] = useState<Maybe<TransactionReceipt>>(null)
|
||||
@ -36,8 +36,8 @@ export const useTransactionStatus = ({ txHash, chainId }: { txHash: string; chai
|
||||
if (!txReceipt) {
|
||||
setStatus(TRANSACTION_STATUS.NOT_FOUND)
|
||||
setDescription(getTransactionStatusDescription(TRANSACTION_STATUS.NOT_FOUND))
|
||||
setMessagesId([txHash])
|
||||
const timeoutId = setTimeout(() => getReceipt(), 5000)
|
||||
setMessages([{ id: txHash, data: '' }])
|
||||
const timeoutId = setTimeout(() => getReceipt(), HOME_RPC_POLLING_INTERVAL)
|
||||
subscriptions.push(timeoutId)
|
||||
} else {
|
||||
const blockNumber = txReceipt.blockNumber
|
||||
@ -46,23 +46,23 @@ export const useTransactionStatus = ({ txHash, chainId }: { txHash: string; chai
|
||||
setTimestamp(blockTimestamp)
|
||||
|
||||
if (txReceipt.status) {
|
||||
let bridgeMessagesId
|
||||
let bridgeMessages: Array<MessageObject>
|
||||
if (isHome) {
|
||||
bridgeMessagesId = getHomeMessagesFromReceipt(txReceipt, home.web3, home.bridgeAddress)
|
||||
bridgeMessages = getHomeMessagesFromReceipt(txReceipt, home.web3, home.bridgeAddress)
|
||||
} else {
|
||||
bridgeMessagesId = getForeignMessagesFromReceipt(txReceipt, foreign.web3, foreign.bridgeAddress)
|
||||
bridgeMessages = getForeignMessagesFromReceipt(txReceipt, foreign.web3, foreign.bridgeAddress)
|
||||
}
|
||||
|
||||
if (bridgeMessagesId.length === 0) {
|
||||
setMessagesId([txHash])
|
||||
if (bridgeMessages.length === 0) {
|
||||
setMessages([{ id: txHash, data: '' }])
|
||||
setStatus(TRANSACTION_STATUS.SUCCESS_NO_MESSAGES)
|
||||
setDescription(getTransactionStatusDescription(TRANSACTION_STATUS.SUCCESS_NO_MESSAGES, blockTimestamp))
|
||||
} else if (bridgeMessagesId.length === 1) {
|
||||
setMessagesId(bridgeMessagesId)
|
||||
} else if (bridgeMessages.length === 1) {
|
||||
setMessages(bridgeMessages)
|
||||
setStatus(TRANSACTION_STATUS.SUCCESS_ONE_MESSAGE)
|
||||
setDescription(getTransactionStatusDescription(TRANSACTION_STATUS.SUCCESS_ONE_MESSAGE, blockTimestamp))
|
||||
} else {
|
||||
setMessagesId(bridgeMessagesId)
|
||||
setMessages(bridgeMessages)
|
||||
setStatus(TRANSACTION_STATUS.SUCCESS_MULTIPLE_MESSAGES)
|
||||
setDescription(
|
||||
getTransactionStatusDescription(TRANSACTION_STATUS.SUCCESS_MULTIPLE_MESSAGES, blockTimestamp)
|
||||
@ -89,7 +89,7 @@ export const useTransactionStatus = ({ txHash, chainId }: { txHash: string; chai
|
||||
)
|
||||
|
||||
return {
|
||||
messagesId,
|
||||
messages,
|
||||
status,
|
||||
description,
|
||||
receipt,
|
||||
|
64
alm/src/services/BlockNumberProvider.ts
Normal file
64
alm/src/services/BlockNumberProvider.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import Web3 from 'web3'
|
||||
import differenceInMilliseconds from 'date-fns/differenceInMilliseconds'
|
||||
import { HOME_RPC_POLLING_INTERVAL } from '../config/constants'
|
||||
|
||||
export class BlockNumberProvider {
|
||||
private running: number
|
||||
private web3: Maybe<Web3>
|
||||
private ref: number | undefined
|
||||
private value: Maybe<number>
|
||||
private lastValueTimestamp: Maybe<Date>
|
||||
private readonly interval: number
|
||||
|
||||
constructor(interval = 5000) {
|
||||
this.running = 0
|
||||
this.web3 = null
|
||||
this.ref = undefined
|
||||
this.value = null
|
||||
this.lastValueTimestamp = null
|
||||
this.interval = interval
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
start(web3: Maybe<Web3>) {
|
||||
if (!this.running) {
|
||||
clearTimeout(this.ref)
|
||||
this.web3 = web3
|
||||
this.running = this.running + 1
|
||||
this.fetchLastBlock()
|
||||
} else {
|
||||
this.running = this.running + 1
|
||||
}
|
||||
}
|
||||
|
||||
stop() {
|
||||
this.running = this.running - 1
|
||||
|
||||
if (!this.running) {
|
||||
clearTimeout(this.ref)
|
||||
this.ref = undefined
|
||||
this.web3 = null
|
||||
}
|
||||
}
|
||||
|
||||
get() {
|
||||
return this.value
|
||||
}
|
||||
|
||||
private async fetchLastBlock() {
|
||||
if (!this.web3) return
|
||||
const now = new Date()
|
||||
const distance = differenceInMilliseconds(now, this.lastValueTimestamp || 0)
|
||||
|
||||
if (distance >= this.interval) {
|
||||
this.value = await this.web3.eth.getBlockNumber()
|
||||
this.lastValueTimestamp = now
|
||||
}
|
||||
|
||||
this.ref = setTimeout(() => this.fetchLastBlock(), this.interval)
|
||||
}
|
||||
}
|
||||
|
||||
export const homeBlockNumberProvider = new BlockNumberProvider(HOME_RPC_POLLING_INTERVAL)
|
||||
export const foreignBlockNumberProvider = new BlockNumberProvider(HOME_RPC_POLLING_INTERVAL)
|
17
alm/src/services/ValidatorsCache.ts
Normal file
17
alm/src/services/ValidatorsCache.ts
Normal file
@ -0,0 +1,17 @@
|
||||
class ValidatorsCache {
|
||||
private readonly store: { [key: string]: boolean }
|
||||
|
||||
constructor() {
|
||||
this.store = {}
|
||||
}
|
||||
|
||||
get(key: string) {
|
||||
return this.store[key]
|
||||
}
|
||||
|
||||
set(key: string, value: boolean) {
|
||||
this.store[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
export default new ValidatorsCache()
|
@ -9,17 +9,27 @@ import {
|
||||
FOREIGN_NETWORK_NAME
|
||||
} from '../config/constants'
|
||||
import Web3 from 'web3'
|
||||
import { useBridgeContracts } from '../hooks/useBridgeContracts'
|
||||
import { Contract } from 'web3-eth-contract'
|
||||
|
||||
export interface NetworkParams {
|
||||
export interface BaseNetworkParams {
|
||||
chainId: number
|
||||
name: string
|
||||
web3: Maybe<Web3>
|
||||
bridgeAddress: string
|
||||
bridgeContract: Maybe<Contract>
|
||||
blockConfirmations: number
|
||||
}
|
||||
|
||||
export interface HomeNetworkParams extends BaseNetworkParams {
|
||||
validatorContract: Maybe<Contract>
|
||||
requiredSignatures: number
|
||||
validatorList: Array<string>
|
||||
}
|
||||
|
||||
export interface StateContext {
|
||||
home: NetworkParams
|
||||
foreign: NetworkParams
|
||||
home: HomeNetworkParams
|
||||
foreign: BaseNetworkParams
|
||||
loading: boolean
|
||||
}
|
||||
|
||||
@ -28,13 +38,20 @@ const initialState = {
|
||||
chainId: 0,
|
||||
name: '',
|
||||
web3: null,
|
||||
bridgeAddress: HOME_BRIDGE_ADDRESS
|
||||
bridgeAddress: HOME_BRIDGE_ADDRESS,
|
||||
bridgeContract: null,
|
||||
blockConfirmations: 0,
|
||||
validatorContract: null,
|
||||
requiredSignatures: 0,
|
||||
validatorList: []
|
||||
},
|
||||
foreign: {
|
||||
chainId: 0,
|
||||
name: '',
|
||||
web3: null,
|
||||
bridgeAddress: FOREIGN_BRIDGE_ADDRESS
|
||||
bridgeAddress: FOREIGN_BRIDGE_ADDRESS,
|
||||
bridgeContract: null,
|
||||
blockConfirmations: 0
|
||||
},
|
||||
loading: true
|
||||
}
|
||||
@ -44,16 +61,35 @@ const StateContext = createContext<StateContext>(initialState)
|
||||
export const StateProvider = ({ children }: { children: ReactNode }) => {
|
||||
const homeNetwork = useNetwork(HOME_RPC_URL)
|
||||
const foreignNetwork = useNetwork(FOREIGN_RPC_URL)
|
||||
const {
|
||||
homeBridge,
|
||||
foreignBridge,
|
||||
homeBlockConfirmations,
|
||||
foreignBlockConfirmations,
|
||||
homeValidatorContract,
|
||||
homeRequiredSignatures,
|
||||
homeValidatorList
|
||||
} = useBridgeContracts({
|
||||
homeWeb3: homeNetwork.web3,
|
||||
foreignWeb3: foreignNetwork.web3
|
||||
})
|
||||
|
||||
const value = {
|
||||
home: {
|
||||
bridgeAddress: HOME_BRIDGE_ADDRESS,
|
||||
name: HOME_NETWORK_NAME,
|
||||
bridgeContract: homeBridge,
|
||||
blockConfirmations: homeBlockConfirmations,
|
||||
validatorContract: homeValidatorContract,
|
||||
requiredSignatures: homeRequiredSignatures,
|
||||
validatorList: homeValidatorList,
|
||||
...homeNetwork
|
||||
},
|
||||
foreign: {
|
||||
bridgeAddress: FOREIGN_BRIDGE_ADDRESS,
|
||||
name: FOREIGN_NETWORK_NAME,
|
||||
bridgeContract: foreignBridge,
|
||||
blockConfirmations: foreignBlockConfirmations,
|
||||
...foreignNetwork
|
||||
},
|
||||
loading: homeNetwork.loading || foreignNetwork.loading
|
||||
|
@ -4,6 +4,14 @@ const theme = {
|
||||
colorPrimary: '#272727',
|
||||
colorGrey: '#272727',
|
||||
colorLightGrey: '#272727',
|
||||
linkColor: '#ffffff'
|
||||
linkColor: '#ffffff',
|
||||
success: {
|
||||
textColor: '#00c9a7',
|
||||
backgroundColor: '#004d40'
|
||||
},
|
||||
notRequired: {
|
||||
textColor: '#bdbdbd',
|
||||
backgroundColor: '#424242'
|
||||
}
|
||||
}
|
||||
export default theme
|
||||
|
@ -20,6 +20,10 @@ export const GlobalStyle = createGlobalStyle<{ theme: ThemeType }>`
|
||||
--color-primary: ${props => props.theme.colorPrimary};
|
||||
--color-grey: ${props => props.theme.colorGrey};
|
||||
--color-lightGrey: ${props => props.theme.colorLightGrey};
|
||||
--link-color: ${props => props.theme.linkColor}
|
||||
--link-color: ${props => props.theme.linkColor};
|
||||
--success-color: ${props => props.theme.success.textColor};
|
||||
--success-bg-color: ${props => props.theme.success.backgroundColor};
|
||||
--not-required-color: ${props => props.theme.notRequired.textColor};
|
||||
--not-required-bg-color: ${props => props.theme.notRequired.backgroundColor};
|
||||
}
|
||||
`
|
||||
|
20
alm/src/utils/contract.ts
Normal file
20
alm/src/utils/contract.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { Contract } from 'web3-eth-contract'
|
||||
|
||||
export const getRequiredBlockConfirmations = async (contract: Contract) => {
|
||||
const blockConfirmations = await contract.methods.requiredBlockConfirmations().call()
|
||||
return parseInt(blockConfirmations)
|
||||
}
|
||||
|
||||
export const getValidatorAddress = (contract: Contract) => contract.methods.validatorContract().call()
|
||||
|
||||
export const getRequiredSignatures = async (contract: Contract) => {
|
||||
const requiredSignatures = await contract.methods.requiredSignatures().call()
|
||||
return parseInt(requiredSignatures)
|
||||
}
|
||||
|
||||
export const getValidatorList = (contract: Contract) => contract.methods.validatorList().call()
|
||||
|
||||
export const getMessagesSigned = (contract: Contract, hash: string) => contract.methods.messagesSigned(hash).call()
|
||||
|
||||
export const getAffirmationsSigned = (contract: Contract, hash: string) =>
|
||||
contract.methods.affirmationsSigned(hash).call()
|
51
alm/src/utils/executionWaitingForBlocks.ts
Normal file
51
alm/src/utils/executionWaitingForBlocks.ts
Normal file
@ -0,0 +1,51 @@
|
||||
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) {
|
||||
setWaitingBlocksForExecution(false)
|
||||
setWaitingBlocksForExecutionResolved(true)
|
||||
blockProvider.stop()
|
||||
} else {
|
||||
let nextInterval = interval
|
||||
if (!currentBlock) {
|
||||
nextInterval = 500
|
||||
} else {
|
||||
setWaitingBlocksForExecution(true)
|
||||
setExecutionData({
|
||||
status: VALIDATOR_CONFIRMATION_STATUS.WAITING,
|
||||
validator: collectedSignaturesEvent.returnValues.authorityResponsibleForRelay,
|
||||
txHash: '',
|
||||
timestamp: 0,
|
||||
executionResult: false
|
||||
})
|
||||
}
|
||||
const timeoutId = setTimeout(
|
||||
() =>
|
||||
checkWaitingBlocksForExecution(
|
||||
blockProvider,
|
||||
interval,
|
||||
targetBlock,
|
||||
collectedSignaturesEvent,
|
||||
setWaitingBlocksForExecution,
|
||||
setWaitingBlocksForExecutionResolved,
|
||||
setExecutionData,
|
||||
subscriptions
|
||||
),
|
||||
nextInterval
|
||||
)
|
||||
subscriptions.push(timeoutId)
|
||||
}
|
||||
}
|
53
alm/src/utils/getCollectedSignaturesEvent.ts
Normal file
53
alm/src/utils/getCollectedSignaturesEvent.ts
Normal file
@ -0,0 +1,53 @@
|
||||
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<Web3>,
|
||||
contract: Maybe<Contract>,
|
||||
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)
|
||||
homeBlockNumberProvider.stop()
|
||||
} 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)
|
||||
}
|
||||
}
|
82
alm/src/utils/getConfirmationsForTx.ts
Normal file
82
alm/src/utils/getConfirmationsForTx.ts
Normal file
@ -0,0 +1,82 @@
|
||||
import Web3 from 'web3'
|
||||
import { Contract } from 'web3-eth-contract'
|
||||
import validatorsCache from '../services/ValidatorsCache'
|
||||
import { HOME_RPC_POLLING_INTERVAL, VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
||||
|
||||
export const getConfirmationsForTx = async (
|
||||
messageData: string,
|
||||
web3: Maybe<Web3>,
|
||||
validatorList: string[],
|
||||
bridgeContract: Maybe<Contract>,
|
||||
confirmationContractMethod: Function,
|
||||
setResult: Function,
|
||||
requiredSignatures: number,
|
||||
setSignatureCollected: Function,
|
||||
waitingBlocksResolved: boolean,
|
||||
subscriptions: number[]
|
||||
) => {
|
||||
if (!web3 || !validatorList || !bridgeContract || !waitingBlocksResolved) return
|
||||
const hashMsg = web3.utils.soliditySha3Raw(messageData)
|
||||
let validatorConfirmations = await Promise.all(
|
||||
validatorList.map(async validator => {
|
||||
const hashSenderMsg = web3.utils.soliditySha3Raw(validator, hashMsg)
|
||||
|
||||
const signatureFromCache = validatorsCache.get(hashSenderMsg)
|
||||
if (signatureFromCache) {
|
||||
return {
|
||||
validator,
|
||||
status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS
|
||||
}
|
||||
}
|
||||
|
||||
const confirmed = await confirmationContractMethod(bridgeContract, hashSenderMsg)
|
||||
const status = confirmed ? VALIDATOR_CONFIRMATION_STATUS.SUCCESS : VALIDATOR_CONFIRMATION_STATUS.UNDEFINED
|
||||
|
||||
// If validator confirmed signature, we cache the result to avoid doing future requests for a result that won't change
|
||||
if (confirmed) {
|
||||
validatorsCache.set(hashSenderMsg, confirmed)
|
||||
}
|
||||
|
||||
return {
|
||||
validator,
|
||||
status
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
const successConfirmations = validatorConfirmations.filter(c => c.status === VALIDATOR_CONFIRMATION_STATUS.SUCCESS)
|
||||
|
||||
// If signatures not collected, it needs to retry in the next blocks
|
||||
if (successConfirmations.length !== requiredSignatures) {
|
||||
const timeoutId = setTimeout(
|
||||
() =>
|
||||
getConfirmationsForTx(
|
||||
messageData,
|
||||
web3,
|
||||
validatorList,
|
||||
bridgeContract,
|
||||
confirmationContractMethod,
|
||||
setResult,
|
||||
requiredSignatures,
|
||||
setSignatureCollected,
|
||||
waitingBlocksResolved,
|
||||
subscriptions
|
||||
),
|
||||
HOME_RPC_POLLING_INTERVAL
|
||||
)
|
||||
subscriptions.push(timeoutId)
|
||||
} else {
|
||||
// If signatures collected, it should set other signatures as not required
|
||||
const notSuccessConfirmations = validatorConfirmations.filter(
|
||||
c => c.status !== VALIDATOR_CONFIRMATION_STATUS.SUCCESS
|
||||
)
|
||||
const notRequiredConfirmations = notSuccessConfirmations.map(c => ({
|
||||
validator: c.validator,
|
||||
status: VALIDATOR_CONFIRMATION_STATUS.NOT_REQUIRED
|
||||
}))
|
||||
|
||||
validatorConfirmations = [...successConfirmations, ...notRequiredConfirmations]
|
||||
setSignatureCollected(true)
|
||||
}
|
||||
setResult(validatorConfirmations)
|
||||
}
|
60
alm/src/utils/getFinalizationEvent.ts
Normal file
60
alm/src/utils/getFinalizationEvent.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { Contract, EventData } from 'web3-eth-contract'
|
||||
import Web3 from 'web3'
|
||||
import { VALIDATOR_CONFIRMATION_STATUS } from '../config/constants'
|
||||
import { ExecutionData } from '../hooks/useMessageConfirmations'
|
||||
|
||||
export const getFinalizationEvent = async (
|
||||
contract: Maybe<Contract>,
|
||||
eventName: string,
|
||||
web3: Maybe<Web3>,
|
||||
setResult: React.Dispatch<React.SetStateAction<ExecutionData>>,
|
||||
waitingBlocksResolved: boolean,
|
||||
messageId: string,
|
||||
interval: number,
|
||||
subscriptions: number[]
|
||||
) => {
|
||||
if (!contract || !web3 || !waitingBlocksResolved) return
|
||||
// Since it filters by the message id, only one event will be fetched
|
||||
// so there is no need to limit the range of the block to reduce the network traffic
|
||||
const events: EventData[] = await contract.getPastEvents(eventName, {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest',
|
||||
filter: {
|
||||
messageId
|
||||
}
|
||||
})
|
||||
if (events.length > 0) {
|
||||
const event = events[0]
|
||||
const [txReceipt, block] = await Promise.all([
|
||||
web3.eth.getTransactionReceipt(event.transactionHash),
|
||||
web3.eth.getBlock(event.blockNumber)
|
||||
])
|
||||
|
||||
const blockTimestamp = typeof block.timestamp === 'string' ? parseInt(block.timestamp) : block.timestamp
|
||||
const validatorAddress = web3.utils.toChecksumAddress(txReceipt.from)
|
||||
|
||||
setResult({
|
||||
status: VALIDATOR_CONFIRMATION_STATUS.SUCCESS,
|
||||
validator: validatorAddress,
|
||||
txHash: event.transactionHash,
|
||||
timestamp: blockTimestamp,
|
||||
executionResult: event.returnValues.status
|
||||
})
|
||||
} else {
|
||||
const timeoutId = setTimeout(
|
||||
() =>
|
||||
getFinalizationEvent(
|
||||
contract,
|
||||
eventName,
|
||||
web3,
|
||||
setResult,
|
||||
waitingBlocksResolved,
|
||||
messageId,
|
||||
interval,
|
||||
subscriptions
|
||||
),
|
||||
interval
|
||||
)
|
||||
subscriptions.push(timeoutId)
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import { formatDistance } from 'date-fns'
|
||||
import { TRANSACTION_STATUS_DESCRIPTION } from '../config/descriptions'
|
||||
import { CONFIRMATIONS_STATUS_DESCRIPTION, TRANSACTION_STATUS_DESCRIPTION } from '../config/descriptions'
|
||||
import { FOREIGN_EXPLORER_TX_TEMPLATE, HOME_EXPLORER_TX_TEMPLATE } from '../config/constants'
|
||||
|
||||
export const validTxHash = (txHash: string) => /^0x[a-fA-F0-9]{64}$/.test(txHash)
|
||||
@ -30,3 +30,12 @@ export const getTransactionStatusDescription = (status: string, timestamp: Maybe
|
||||
|
||||
return description
|
||||
}
|
||||
|
||||
export const getConfirmationsStatusDescription = (status: string, home: string, foreign: string) => {
|
||||
let description = CONFIRMATIONS_STATUS_DESCRIPTION[status]
|
||||
|
||||
description = description.replace('%homeChain', home)
|
||||
description = description.replace('%foreignChain', foreign)
|
||||
|
||||
return description
|
||||
}
|
||||
|
50
alm/src/utils/signatureWaitingForBlocks.ts
Normal file
50
alm/src/utils/signatureWaitingForBlocks.ts
Normal file
@ -0,0 +1,50 @@
|
||||
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) {
|
||||
setWaitingStatus(false)
|
||||
setWaitingBlocksResolved(true)
|
||||
blockProvider.stop()
|
||||
} 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)
|
||||
}
|
||||
}
|
@ -4,6 +4,11 @@ import { AbiItem } from 'web3-utils'
|
||||
import memoize from 'fast-memoize'
|
||||
import { HOME_AMB_ABI, FOREIGN_AMB_ABI } from '../../../commons'
|
||||
|
||||
export interface MessageObject {
|
||||
id: string
|
||||
data: string
|
||||
}
|
||||
|
||||
const rawGetWeb3 = (url: string) => new Web3(new Web3.providers.HttpProvider(url))
|
||||
const memoized = memoize(rawGetWeb3)
|
||||
|
||||
@ -14,11 +19,20 @@ export const filterEventsByAbi = (
|
||||
web3: Web3,
|
||||
bridgeAddress: string,
|
||||
eventAbi: AbiItem
|
||||
) => {
|
||||
): MessageObject[] => {
|
||||
const eventHash = web3.eth.abi.encodeEventSignature(eventAbi)
|
||||
const events = txReceipt.logs.filter(e => e.address === bridgeAddress && e.topics[0] === eventHash)
|
||||
|
||||
return events.map(e => e.topics[1])
|
||||
return events.map(e => {
|
||||
let decodedLogs: { [p: string]: string } = {
|
||||
messageId: '',
|
||||
encodedData: ''
|
||||
}
|
||||
if (eventAbi && eventAbi.inputs && eventAbi.inputs.length) {
|
||||
decodedLogs = web3.eth.abi.decodeLog(eventAbi.inputs, e.data, [e.topics[1]])
|
||||
}
|
||||
return { id: decodedLogs.messageId, data: decodedLogs.encodedData }
|
||||
})
|
||||
}
|
||||
|
||||
export const getHomeMessagesFromReceipt = (txReceipt: TransactionReceipt, web3: Web3, bridgeAddress: string) => {
|
||||
|
394
yarn.lock
394
yarn.lock
@ -1304,21 +1304,6 @@
|
||||
"@ethersproject/properties" ">=5.0.0-beta.131"
|
||||
"@ethersproject/strings" ">=5.0.0-beta.130"
|
||||
|
||||
"@ethersproject/abi@5.0.0-beta.153":
|
||||
version "5.0.0-beta.153"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee"
|
||||
integrity sha512-aXweZ1Z7vMNzJdLpR1CZUAIgnwjrZeUSvN9syCwlBaEBUFJmFY+HHnfuTI5vIhVs/mRkfJVrbEyl51JZQqyjAg==
|
||||
dependencies:
|
||||
"@ethersproject/address" ">=5.0.0-beta.128"
|
||||
"@ethersproject/bignumber" ">=5.0.0-beta.130"
|
||||
"@ethersproject/bytes" ">=5.0.0-beta.129"
|
||||
"@ethersproject/constants" ">=5.0.0-beta.128"
|
||||
"@ethersproject/hash" ">=5.0.0-beta.128"
|
||||
"@ethersproject/keccak256" ">=5.0.0-beta.127"
|
||||
"@ethersproject/logger" ">=5.0.0-beta.129"
|
||||
"@ethersproject/properties" ">=5.0.0-beta.131"
|
||||
"@ethersproject/strings" ">=5.0.0-beta.130"
|
||||
|
||||
"@ethersproject/address@>=5.0.0-beta.128":
|
||||
version "5.0.0-beta.134"
|
||||
resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.0.0-beta.134.tgz#9c1790c87b763dc547ac12e2dbc9fa78d0799a71"
|
||||
@ -4868,7 +4853,7 @@ balanced-match@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||
|
||||
base-x@^3.0.2, base-x@^3.0.8:
|
||||
base-x@^3.0.2:
|
||||
version "3.0.8"
|
||||
resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d"
|
||||
integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA==
|
||||
@ -5804,17 +5789,6 @@ ci-info@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
|
||||
integrity sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==
|
||||
|
||||
cids@^0.7.1:
|
||||
version "0.7.5"
|
||||
resolved "https://registry.yarnpkg.com/cids/-/cids-0.7.5.tgz#60a08138a99bfb69b6be4ceb63bfef7a396b28b2"
|
||||
integrity sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==
|
||||
dependencies:
|
||||
buffer "^5.5.0"
|
||||
class-is "^1.1.0"
|
||||
multibase "~0.6.0"
|
||||
multicodec "^1.0.0"
|
||||
multihashes "~0.4.15"
|
||||
|
||||
cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de"
|
||||
@ -5823,11 +5797,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
|
||||
inherits "^2.0.1"
|
||||
safe-buffer "^5.0.1"
|
||||
|
||||
class-is@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/class-is/-/class-is-1.1.0.tgz#9d3c0fba0440d211d843cec3dedfa48055005825"
|
||||
integrity sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==
|
||||
|
||||
class-utils@^0.3.5:
|
||||
version "0.3.6"
|
||||
resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463"
|
||||
@ -6293,15 +6262,6 @@ content-disposition@0.5.3:
|
||||
dependencies:
|
||||
safe-buffer "5.1.2"
|
||||
|
||||
content-hash@^2.5.2:
|
||||
version "2.5.2"
|
||||
resolved "https://registry.yarnpkg.com/content-hash/-/content-hash-2.5.2.tgz#bbc2655e7c21f14fd3bfc7b7d4bfe6e454c9e211"
|
||||
integrity sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==
|
||||
dependencies:
|
||||
cids "^0.7.1"
|
||||
multicodec "^0.5.5"
|
||||
multihashes "^0.4.15"
|
||||
|
||||
content-type@~1.0.4:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b"
|
||||
@ -13821,22 +13781,6 @@ ms@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
|
||||
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
|
||||
|
||||
multibase@^0.7.0:
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.7.0.tgz#1adfc1c50abe05eefeb5091ac0c2728d6b84581b"
|
||||
integrity sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==
|
||||
dependencies:
|
||||
base-x "^3.0.8"
|
||||
buffer "^5.5.0"
|
||||
|
||||
multibase@~0.6.0:
|
||||
version "0.6.1"
|
||||
resolved "https://registry.yarnpkg.com/multibase/-/multibase-0.6.1.tgz#b76df6298536cc17b9f6a6db53ec88f85f8cc12b"
|
||||
integrity sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==
|
||||
dependencies:
|
||||
base-x "^3.0.8"
|
||||
buffer "^5.5.0"
|
||||
|
||||
multicast-dns-service-types@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901"
|
||||
@ -13850,30 +13794,6 @@ multicast-dns@^6.0.1:
|
||||
dns-packet "^1.3.1"
|
||||
thunky "^1.0.2"
|
||||
|
||||
multicodec@^0.5.5:
|
||||
version "0.5.7"
|
||||
resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-0.5.7.tgz#1fb3f9dd866a10a55d226e194abba2dcc1ee9ffd"
|
||||
integrity sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==
|
||||
dependencies:
|
||||
varint "^5.0.0"
|
||||
|
||||
multicodec@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/multicodec/-/multicodec-1.0.1.tgz#4e2812d726b9f7c7d615d3ebc5787d36a08680f9"
|
||||
integrity sha512-yrrU/K8zHyAH2B0slNVeq3AiwluflHpgQ3TAzwNJcuO2AoPyXgBT2EDkdbP1D8B/yFOY+S2hDYmFlI1vhVFkQw==
|
||||
dependencies:
|
||||
buffer "^5.5.0"
|
||||
varint "^5.0.0"
|
||||
|
||||
multihashes@^0.4.15, multihashes@~0.4.15:
|
||||
version "0.4.19"
|
||||
resolved "https://registry.yarnpkg.com/multihashes/-/multihashes-0.4.19.tgz#d7493cf028e48747122f350908ea13d12d204813"
|
||||
integrity sha512-ej74GAfA20imjj00RO5h34aY3pGUFyzn9FJZFWwdeUHlHTkKmv90FrNpvYT4jYf1XXCy5O/5EjVnxTaESgOM6A==
|
||||
dependencies:
|
||||
buffer "^5.5.0"
|
||||
multibase "^0.7.0"
|
||||
varint "^5.0.0"
|
||||
|
||||
multimatch@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/multimatch/-/multimatch-3.0.0.tgz#0e2534cc6bc238d9ab67e1b9cd5fcd85a6dbf70b"
|
||||
@ -20113,11 +20033,6 @@ value-or-function@^3.0.0:
|
||||
resolved "https://registry.yarnpkg.com/value-or-function/-/value-or-function-3.0.0.tgz#1c243a50b595c1be54a754bfece8563b9ff8d813"
|
||||
integrity sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=
|
||||
|
||||
varint@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.0.tgz#d826b89f7490732fabc0c0ed693ed475dcb29ebf"
|
||||
integrity sha1-2Ca4n3SQcy+rwMDtaT7Uddyynr8=
|
||||
|
||||
vary@^1, vary@~1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
|
||||
@ -20324,10 +20239,10 @@ web3-bzz@1.2.4:
|
||||
swarm-js "0.1.39"
|
||||
underscore "1.9.1"
|
||||
|
||||
web3-bzz@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.8.tgz#7ff2c2de362f82ae3825e48c70ec63b3aca2b8ef"
|
||||
integrity sha512-jbi24/s2tT7FYuN+ktRvTa5em0GxhqcIYQ8FnD3Zb/ZoEPi+/7rH0Hh+WDol0pSZL+wdz/iM+Z2C9NE42z6EmQ==
|
||||
web3-bzz@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.7.tgz#aa0f3d162f0777a5f35367dc5b70012dd1e129d0"
|
||||
integrity sha512-iTIWBR+Z+Bn09WprtKm46LmyNOasg2lUn++AjXkBTB8UNxlUybxtza84yl2ETTZUs0zuFzdSSAEgbjhygG+9oA==
|
||||
dependencies:
|
||||
"@types/node" "^10.12.18"
|
||||
got "9.6.0"
|
||||
@ -20361,14 +20276,14 @@ web3-core-helpers@1.2.4:
|
||||
web3-eth-iban "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-core-helpers@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.8.tgz#86776d8f658b63bb630c84a314686661e599aa68"
|
||||
integrity sha512-Wrl7ZPKn3Xyg0Hl5+shDnJcLP+EtTfThmQ1eCJLcg/BZqvLUR1SkOslNlhEojcYeBwhhymAKs8dfQbtYi+HMnw==
|
||||
web3-core-helpers@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.7.tgz#522f859775ea0d15e7e40359c46d4efc5da92aee"
|
||||
integrity sha512-bdU++9QATGeCetVrMp8pV97aQtVkN5oLBf/TWu/qumC6jK/YqrvLlBJLdwbz0QveU8zOSap6GCvJbqKvmmbV2A==
|
||||
dependencies:
|
||||
underscore "1.9.1"
|
||||
web3-eth-iban "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-eth-iban "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-core-method@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20403,16 +20318,16 @@ web3-core-method@1.2.4:
|
||||
web3-core-subscriptions "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-core-method@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.8.tgz#f28a79935432aebfa019e4a50f9b6ae6c9ef4297"
|
||||
integrity sha512-69qbvOgx0Frw46dXvEKzYgtaPXpUaQAlQmczgb0ZUBHsEU2K7jTtFgBy6kVBgAwsXDvoZ99AX4SjpY2dTMwPkw==
|
||||
web3-core-method@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.7.tgz#73fd80d2bf0765ff6efc454db49ac83d1769a45e"
|
||||
integrity sha512-e1TI0QUnByDMbQ8QHwnjxfjKw0LIgVRY4TYrlPijET9ebqUJU1HCayn/BHIMpV6LKyR1fQj9EldWyT64wZQXkg==
|
||||
dependencies:
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-promievent "1.2.8"
|
||||
web3-core-subscriptions "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-core-helpers "1.2.7"
|
||||
web3-core-promievent "1.2.7"
|
||||
web3-core-subscriptions "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-core-promievent@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20438,10 +20353,10 @@ web3-core-promievent@1.2.4:
|
||||
any-promise "1.3.0"
|
||||
eventemitter3 "3.1.2"
|
||||
|
||||
web3-core-promievent@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.8.tgz#a93ca2a19cae8b60883412619e04e69e11804eb5"
|
||||
integrity sha512-3EdRieaHpBVVhfGjoREQfdoCM3xC0WwWjXXzT6oTldotfYC38kwk/GW8c8txYiLP/KxhslAN1cJSlXNOJjKSog==
|
||||
web3-core-promievent@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.7.tgz#fc7fa489f4cf76a040800f3dfd4b45c51bd3a39f"
|
||||
integrity sha512-jNmsM/czCeMGQqKKwM9/HZVTJVIF96hdMVNN/V9TGvp+EEE7vDhB4pUocDnc/QF9Z/5QFBCVmvNWttlRgZmU0A==
|
||||
dependencies:
|
||||
eventemitter3 "3.1.2"
|
||||
|
||||
@ -20478,16 +20393,16 @@ web3-core-requestmanager@1.2.4:
|
||||
web3-providers-ipc "1.2.4"
|
||||
web3-providers-ws "1.2.4"
|
||||
|
||||
web3-core-requestmanager@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.8.tgz#da7259e72a433858d04c59b999c5116bfb797c09"
|
||||
integrity sha512-bwc2ABG6yzgTy28fv4t59g+tf6+UmTRMoF8HqTeiNDffoMKP2akyKFZeu1oD2gE7j/7GA75TAUjwJ7pH9ek1MA==
|
||||
web3-core-requestmanager@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.7.tgz#9da0efce898ead7004d4ac50f748f5131cfe4d79"
|
||||
integrity sha512-HJb/txjHixu1dxIebiZQKBoJCaNu4gsh7mq/uj6Z/w6tIHbybL90s/7ADyMED353yyJ2tDWtYJqeMVAR+KtdaA==
|
||||
dependencies:
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-providers-http "1.2.8"
|
||||
web3-providers-ipc "1.2.8"
|
||||
web3-providers-ws "1.2.8"
|
||||
web3-core-helpers "1.2.7"
|
||||
web3-providers-http "1.2.7"
|
||||
web3-providers-ipc "1.2.7"
|
||||
web3-providers-ws "1.2.7"
|
||||
|
||||
web3-core-subscriptions@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20516,14 +20431,14 @@ web3-core-subscriptions@1.2.4:
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.2.4"
|
||||
|
||||
web3-core-subscriptions@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.8.tgz#50945498fb0bd655f842cbcc13873d96956aa93e"
|
||||
integrity sha512-wmsRJ4ipwoF1mlOR+Oo8JdKigpkoVNQtqiRUuyQrTVhJx7GBuSaAIenpBYlkucC+RgByoGybR7Q3tTNJ6z/2tQ==
|
||||
web3-core-subscriptions@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.7.tgz#30c64aede03182832883b17c77e21cbb0933c86e"
|
||||
integrity sha512-W/CzQYOUawdMDvkgA/fmLsnG5aMpbjrs78LZMbc0MFXLpH3ofqAgO2by4QZrrTShUUTeWS0ZuEkFFL/iFrSObw==
|
||||
dependencies:
|
||||
eventemitter3 "3.1.2"
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-helpers "1.2.7"
|
||||
|
||||
web3-core@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20558,18 +20473,18 @@ web3-core@1.2.4:
|
||||
web3-core-requestmanager "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-core@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.8.tgz#2a488bb11519b71e7738265329bddc00fc200dd3"
|
||||
integrity sha512-hvlYWyE1UcLoGa6qF1GoxGgi1quFsZOdwIUIVsAp+sp0plXp/Nqva2lAjJ+FFyWtVKbC7Zq+qwTJ4iP1aN0vTg==
|
||||
web3-core@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.7.tgz#9248b04331e458c76263d758c51b0cc612953900"
|
||||
integrity sha512-QA0MTae0gXcr3KHe3cQ4x56+Wh43ZKWfMwg1gfCc3NNxPRM1jJ8qudzyptCAUcxUGXWpDG8syLIn1APDz5J8BQ==
|
||||
dependencies:
|
||||
"@types/bn.js" "^4.11.4"
|
||||
"@types/node" "^12.6.1"
|
||||
bignumber.js "^9.0.0"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-method "1.2.8"
|
||||
web3-core-requestmanager "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-core-helpers "1.2.7"
|
||||
web3-core-method "1.2.7"
|
||||
web3-core-requestmanager "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-eth-abi@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20600,14 +20515,14 @@ web3-eth-abi@1.2.4:
|
||||
underscore "1.9.1"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-eth-abi@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.8.tgz#7537138f3e5cd1ccf98233fa07f388aa8dc1fff1"
|
||||
integrity sha512-OKp/maLdKHPpQxZhEd0HgnCJFQajsGe42WOG6SVftlgzyR8Jjv4KNm46TKvb3hv5OJTKZWU7nZIxkEG+fyI58w==
|
||||
web3-eth-abi@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.7.tgz#6f3471b578649fddd844a14d397a3dd430fc44a5"
|
||||
integrity sha512-4FnlT1q+D0XBkxSMXlIb/eG337uQeMaUdtVQ4PZ3XzxqpcoDuMgXm4o+3NRxnWmr4AMm6QKjM+hcC7c0mBKcyg==
|
||||
dependencies:
|
||||
"@ethersproject/abi" "5.0.0-beta.153"
|
||||
ethers "4.0.0-beta.3"
|
||||
underscore "1.9.1"
|
||||
web3-utils "1.2.8"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-eth-abi@^1.0.0-beta.24:
|
||||
version "1.2.6"
|
||||
@ -20668,10 +20583,10 @@ web3-eth-accounts@1.2.4:
|
||||
web3-core-method "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-eth-accounts@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.8.tgz#e63afc6d4902f2beb0cf60e6b755c86fa5b5ccd7"
|
||||
integrity sha512-QODqSD4SZN/1oWfvlvsuum6Ud9+2FUTW4VTPJh245YTewCpa0M5+Fzug3UTeUZNv88STwC//dV72zReITNh4ZQ==
|
||||
web3-eth-accounts@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.7.tgz#087f55d04a01b815b93151aac2fc1677436b9c59"
|
||||
integrity sha512-AE7QWi/iIQIjXwlAPtlMabm/OPFF0a1PhxT1EiTckpYNP8fYs6jW7lYxEtJPPJIKqfMjoi1xkEqTVR1YZQ88lg==
|
||||
dependencies:
|
||||
"@web3-js/scrypt-shim" "^0.1.0"
|
||||
crypto-browserify "3.12.0"
|
||||
@ -20680,10 +20595,10 @@ web3-eth-accounts@1.2.8:
|
||||
ethereumjs-tx "^2.1.1"
|
||||
underscore "1.9.1"
|
||||
uuid "3.3.2"
|
||||
web3-core "1.2.8"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-method "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-core "1.2.7"
|
||||
web3-core-helpers "1.2.7"
|
||||
web3-core-method "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-eth-contract@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20728,20 +20643,20 @@ web3-eth-contract@1.2.4:
|
||||
web3-eth-abi "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-eth-contract@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.8.tgz#ff75920ac698a70781edcebbf75287a6d0f14499"
|
||||
integrity sha512-EWRLVhZksbzGAyHd7RaOsakjCJBA2BREWiJmBDlrxDBqw8HltXFzKdkRug/mwVNa5ZYMabKSRF/MMh0Sx06CFw==
|
||||
web3-eth-contract@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.7.tgz#13d7f6003d6221f9a5fd61c2d3b5d039477c9674"
|
||||
integrity sha512-uW23Y0iL7XroRNbf9fWZ1N6OYhEYTJX8gTuYASuRnpYrISN5QGiQML6pq/NCzqypR1bl5E0fuINZQSK/xefIVw==
|
||||
dependencies:
|
||||
"@types/bn.js" "^4.11.4"
|
||||
underscore "1.9.1"
|
||||
web3-core "1.2.8"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-method "1.2.8"
|
||||
web3-core-promievent "1.2.8"
|
||||
web3-core-subscriptions "1.2.8"
|
||||
web3-eth-abi "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-core "1.2.7"
|
||||
web3-core-helpers "1.2.7"
|
||||
web3-core-method "1.2.7"
|
||||
web3-core-promievent "1.2.7"
|
||||
web3-core-subscriptions "1.2.7"
|
||||
web3-eth-abi "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-eth-ens@1.2.4:
|
||||
version "1.2.4"
|
||||
@ -20757,20 +20672,19 @@ web3-eth-ens@1.2.4:
|
||||
web3-eth-contract "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-eth-ens@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.8.tgz#247daddfdbf7533adb0f45cd2f75c75e52f7e678"
|
||||
integrity sha512-zsFXY26BMGkihPkEO5qj9AEqyxPH4mclbzYs1dyrw7sHFmrUvhZc+jLGT9WyQGoujq37RN2l/tlOpCaFVVR8ng==
|
||||
web3-eth-ens@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.7.tgz#0bfa7d4b6c7753abbb31a2eb01a364b538f4c860"
|
||||
integrity sha512-SPRnvUNWQ0CnnTDBteGIJkvFWEizJcAHlVsrFLICwcwFZu+appjX1UOaoGu2h3GXWtc/XZlu7B451Gi+Os2cTg==
|
||||
dependencies:
|
||||
content-hash "^2.5.2"
|
||||
eth-ens-namehash "2.0.8"
|
||||
underscore "1.9.1"
|
||||
web3-core "1.2.8"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-promievent "1.2.8"
|
||||
web3-eth-abi "1.2.8"
|
||||
web3-eth-contract "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-core "1.2.7"
|
||||
web3-core-helpers "1.2.7"
|
||||
web3-core-promievent "1.2.7"
|
||||
web3-eth-abi "1.2.7"
|
||||
web3-eth-contract "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-eth-iban@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20796,13 +20710,13 @@ web3-eth-iban@1.2.4:
|
||||
bn.js "4.11.8"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-eth-iban@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.8.tgz#414e80a7fb2d1ea16490bc2c8fc29a996aec5612"
|
||||
integrity sha512-xgPUOuDOQJYloUS334/wot6jvp6K8JBz8UvQ1tAxU9LO2v2DW+IDTJ5gQ6TdutTmzdDi97KdwhwnQwhQh5Z1PA==
|
||||
web3-eth-iban@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.7.tgz#832809c28586be3c667a713b77a2bcba11b7970f"
|
||||
integrity sha512-2NrClz1PoQ3nSJBd+91ylCOVga9qbTxjRofq/oSCoHVAEvz3WZyttx9k5DC+0rWqwJF1h69ufFvdHAAlmN/4lg==
|
||||
dependencies:
|
||||
bn.js "4.11.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-eth-personal@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20838,17 +20752,17 @@ web3-eth-personal@1.2.4:
|
||||
web3-net "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-eth-personal@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.8.tgz#8ebb27210b4c9c9555a30c5bb2ce8db12f84cd24"
|
||||
integrity sha512-sWhxF1cpF9pB1wMISrOSy/i8IB1NWtvoXT9dfkWtvByGf3JfC2DlnllLaA1f9ohyvxnR+QTgPKgOQDknmqDstw==
|
||||
web3-eth-personal@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.7.tgz#322cc2b14c37737b21772a53e4185686a04bf9be"
|
||||
integrity sha512-2OAa1Spz0uB29dwCM8+1y0So7E47A4gKznjBEwXIYEcUIsvwT5X7ofFhC2XxyRpqlIWZSQAxRSSJFyupRRXzyw==
|
||||
dependencies:
|
||||
"@types/node" "^12.6.1"
|
||||
web3-core "1.2.8"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-method "1.2.8"
|
||||
web3-net "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-core "1.2.7"
|
||||
web3-core-helpers "1.2.7"
|
||||
web3-core-method "1.2.7"
|
||||
web3-net "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-eth@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20905,24 +20819,24 @@ web3-eth@1.2.4:
|
||||
web3-net "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-eth@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.8.tgz#cf6a16fae4d7c12b90cfb6ef570cb1a2acc34c1b"
|
||||
integrity sha512-CEnVIIR1zZQ9vQh/kPFAUbvbbHYkC84y15jdhRUDDGR6bs4FxO2NNWR2YDtNe038lrz747tZahsC9kEiGkJFZQ==
|
||||
web3-eth@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.7.tgz#9427daefd3641200679c2946f77fc184dbfb5b4c"
|
||||
integrity sha512-ljLd0oB4IjWkzFGVan4HkYhJXhSXgn9iaSaxdJixKGntZPgWMJfxeA+uLwTrlxrWzhvy4f+39WnT7wCh5e9TGg==
|
||||
dependencies:
|
||||
underscore "1.9.1"
|
||||
web3-core "1.2.8"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-method "1.2.8"
|
||||
web3-core-subscriptions "1.2.8"
|
||||
web3-eth-abi "1.2.8"
|
||||
web3-eth-accounts "1.2.8"
|
||||
web3-eth-contract "1.2.8"
|
||||
web3-eth-ens "1.2.8"
|
||||
web3-eth-iban "1.2.8"
|
||||
web3-eth-personal "1.2.8"
|
||||
web3-net "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-core "1.2.7"
|
||||
web3-core-helpers "1.2.7"
|
||||
web3-core-method "1.2.7"
|
||||
web3-core-subscriptions "1.2.7"
|
||||
web3-eth-abi "1.2.7"
|
||||
web3-eth-accounts "1.2.7"
|
||||
web3-eth-contract "1.2.7"
|
||||
web3-eth-ens "1.2.7"
|
||||
web3-eth-iban "1.2.7"
|
||||
web3-eth-personal "1.2.7"
|
||||
web3-net "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-net@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -20951,14 +20865,14 @@ web3-net@1.2.4:
|
||||
web3-core-method "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3-net@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.8.tgz#582fc2d4ba32c2e5c7761624e4be7c5434142d66"
|
||||
integrity sha512-Nsq6qgncvvThOjC+sQ+NfDH8L7jclQCFzLFYa9wsd5J6HJ6f5gJl/mv6rsZQX9iDEYDPKkDfyqHktynOBgKWMQ==
|
||||
web3-net@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.7.tgz#c355621a8769c9c1a967c801e7db90c92a0e3808"
|
||||
integrity sha512-j9qeZrS1FNyCeA0BfdLojkxOZQz3FKa1DJI+Dw9fEVhZS68vLOFANu2RB96gR9BoPHo5+k5D3NsKOoxt1gw3Gg==
|
||||
dependencies:
|
||||
web3-core "1.2.8"
|
||||
web3-core-method "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-core "1.2.7"
|
||||
web3-core-method "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
web3-provider-engine@14.0.6:
|
||||
version "14.0.6"
|
||||
@ -21037,12 +20951,12 @@ web3-providers-http@1.2.4:
|
||||
web3-core-helpers "1.2.4"
|
||||
xhr2-cookies "1.1.0"
|
||||
|
||||
web3-providers-http@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.8.tgz#cd7fc4d49df6980b5dd0fb1b5a808bc4b6a0069d"
|
||||
integrity sha512-Esj4SpgabmBDOR4QD3qYapzwFYWHigcdgdjvt/VWT5/7TD10o52hr+Nsvp3/XV5AFrcCMdY+lzKFLVH24u0sww==
|
||||
web3-providers-http@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.7.tgz#31eb15390c103169b3d7d31bdb1ccae9e3f1629d"
|
||||
integrity sha512-vazGx5onuH/zogrwkUaLFJwFcJ6CckP65VFSHoiV+GTQdkOqgoDIha7StKkslvDz4XJ2FuY/zOZHbtuOYeltXQ==
|
||||
dependencies:
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-helpers "1.2.7"
|
||||
xhr2-cookies "1.1.0"
|
||||
|
||||
web3-providers-ipc@1.0.0-beta.30:
|
||||
@ -21072,14 +20986,14 @@ web3-providers-ipc@1.2.4:
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.2.4"
|
||||
|
||||
web3-providers-ipc@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.8.tgz#47be918ddd077999aa14703169b76c807f45d894"
|
||||
integrity sha512-ts3/UXCTRADPASdJ27vBVmcfM+lfG9QVBxGedY6+oNIo5EPxBUtsz94R32sfvFd6ofPsz6gOhK/M/ZKiJoi1sg==
|
||||
web3-providers-ipc@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.7.tgz#4e6716e8723d431df3d6bfa1acd2f7c04e7071ad"
|
||||
integrity sha512-/zc0y724H2zbkV4UbGGMhsEiLfafjagIzfrsWZnyTZUlSB0OGRmmFm2EkLJAgtXrLiodaHHyXKM0vB8S24bxdA==
|
||||
dependencies:
|
||||
oboe "2.1.4"
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-helpers "1.2.7"
|
||||
|
||||
web3-providers-ws@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -21108,15 +21022,15 @@ web3-providers-ws@1.2.4:
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.2.4"
|
||||
|
||||
web3-providers-ws@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.8.tgz#9e6454edc82d753d398c8d1e044632c234434a46"
|
||||
integrity sha512-Gcm0n82wd/XVeGFGTx+v56UqyrV9EyB2r1QFaBx4mS+VHbW2MCOdiRbNDfoZQslflnCWl8oHsivJ8Tya9kqlTQ==
|
||||
web3-providers-ws@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.7.tgz#95b1cc5dc25e9b9d6630d6754f9354313b62f532"
|
||||
integrity sha512-b5XzqDpRkNVe6MFs5K6iqOEyjQikHtg3KuU2/ClCDV37hm0WN4xCRVMC0LwegulbDXZej3zT9+1CYzGaGFREzA==
|
||||
dependencies:
|
||||
"@web3-js/websocket" "^1.0.29"
|
||||
eventemitter3 "^4.0.0"
|
||||
underscore "1.9.1"
|
||||
web3-core-helpers "1.2.8"
|
||||
web3-core-helpers "1.2.7"
|
||||
|
||||
web3-shh@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -21148,15 +21062,15 @@ web3-shh@1.2.4:
|
||||
web3-core-subscriptions "1.2.4"
|
||||
web3-net "1.2.4"
|
||||
|
||||
web3-shh@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.8.tgz#5162d9d13bc6838d390df1cd39e5f87235c1c2ae"
|
||||
integrity sha512-e29qKSfuZWDmxCG/uB48Nth6DCFFr2h2U+uI/fHEuhEjAEkBHopPNLc3ixrCTc6pqMocfJRPHJq/yET9PYN3oQ==
|
||||
web3-shh@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.7.tgz#5382c7bc2f39539eb2841c4576d23ade25720461"
|
||||
integrity sha512-f6PAgcpG0ZAo98KqCmeHoDEx5qzm3d5plet18DkT4U6WIeYowKdec8vZaLPRR7c2XreXFJ2gQf45CB7oqR7U/w==
|
||||
dependencies:
|
||||
web3-core "1.2.8"
|
||||
web3-core-method "1.2.8"
|
||||
web3-core-subscriptions "1.2.8"
|
||||
web3-net "1.2.8"
|
||||
web3-core "1.2.7"
|
||||
web3-core-method "1.2.7"
|
||||
web3-core-subscriptions "1.2.7"
|
||||
web3-net "1.2.7"
|
||||
|
||||
web3-utils@1.0.0-beta.30:
|
||||
version "1.0.0-beta.30"
|
||||
@ -21212,10 +21126,10 @@ web3-utils@1.2.6:
|
||||
underscore "1.9.1"
|
||||
utf8 "3.0.0"
|
||||
|
||||
web3-utils@1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.8.tgz#5321d91715cd4c0869005705a33c4c042a532b18"
|
||||
integrity sha512-9SIVGFLajwlmo5joC4DGxuy2OeDkRCXVWT8JWcDQ+BayNVHyAWGvn0oGkQ0ys14Un0KK6bjjKoD0xYs4k+FaVw==
|
||||
web3-utils@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.7.tgz#b68e232917e4376f81cf38ef79878e5903d18e93"
|
||||
integrity sha512-FBh/CPJND+eiPeUF9KVbTyTZtXNWxPWtByBaWS6e2x4ACazPX711EeNaZaChIOGSLGe6se2n7kg6wnawe/MjuQ==
|
||||
dependencies:
|
||||
bn.js "4.11.8"
|
||||
eth-lib "0.2.7"
|
||||
@ -21266,18 +21180,18 @@ web3@1.2.4:
|
||||
web3-shh "1.2.4"
|
||||
web3-utils "1.2.4"
|
||||
|
||||
web3@^1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.8.tgz#20b24baa769e0224a708ef5bf196a5b83d19540b"
|
||||
integrity sha512-rXUn16VKxn2aIe9v0KX+bSm2JXdq/Vnj3lZ0Rub2Q5YUSycHdCBaDtJRukl/jB5ygAdyr5/cUwvJzhNDJSYsGw==
|
||||
web3@1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.7.tgz#fcb83571036c1c6f475bc984785982a444e8d78e"
|
||||
integrity sha512-jAAJHMfUlTps+jH2li1ckDFEpPrEEriU/ubegSTGRl3KRdNhEqT93+3kd7FHJTn3NgjcyURo2+f7Da1YcZL8Mw==
|
||||
dependencies:
|
||||
web3-bzz "1.2.8"
|
||||
web3-core "1.2.8"
|
||||
web3-eth "1.2.8"
|
||||
web3-eth-personal "1.2.8"
|
||||
web3-net "1.2.8"
|
||||
web3-shh "1.2.8"
|
||||
web3-utils "1.2.8"
|
||||
web3-bzz "1.2.7"
|
||||
web3-core "1.2.7"
|
||||
web3-eth "1.2.7"
|
||||
web3-eth-personal "1.2.7"
|
||||
web3-net "1.2.7"
|
||||
web3-shh "1.2.7"
|
||||
web3-utils "1.2.7"
|
||||
|
||||
webidl-conversions@^4.0.2:
|
||||
version "4.0.2"
|
||||
|
Loading…
Reference in New Issue
Block a user