Apps/Feature #37: add onUserReject event handler (#1354)

* add onUserReject event handler

* fix invoking possibly undefined func

* update sdk version

* yarn lock update

* fix network passing
This commit is contained in:
Mikhail Mikheev 2020-09-15 20:21:03 +04:00 committed by GitHub
parent e000958c28
commit 8a6633db92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 918 additions and 53 deletions

View File

@ -164,7 +164,7 @@
]
},
"dependencies": {
"@gnosis.pm/safe-apps-sdk": "https://github.com/gnosis/safe-apps-sdk.git#development",
"@gnosis.pm/safe-apps-sdk": "0.4.0",
"@gnosis.pm/safe-contracts": "1.1.1-dev.2",
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#1bf397f",
"@gnosis.pm/util-contracts": "2.0.6",

View File

@ -111,6 +111,7 @@ interface CreateTransactionArgs {
type CreateTransactionAction = ThunkAction<Promise<void>, AppReduxState, undefined, AnyAction>
type ConfirmEventHandler = (safeTxHash: string) => void
type RejectEventHandler = () => void
const createTransaction = (
{
@ -125,6 +126,7 @@ const createTransaction = (
origin = null,
}: CreateTransactionArgs,
onUserConfirm?: ConfirmEventHandler,
onUserReject?: RejectEventHandler,
): CreateTransactionAction => async (dispatch: Dispatch, getState: () => AppReduxState): Promise<void> => {
const state = getState()
@ -242,6 +244,21 @@ const createTransaction = (
dispatch(closeSnackbarAction({ key: pendingExecutionKey }))
removeTxFromStore(mockedTx, safeAddress, dispatch, state)
console.error('Tx error: ', error)
// Different wallets return different error messages in this case. This is an assumption that if
// error message includes "user" word, the tx was rejected by user
let errorIncludesUserWord = false
if (typeof error === 'string') {
errorIncludesUserWord = (error as string).includes('User') || (error as string).includes('user')
}
if (error.message) {
errorIncludesUserWord = error.message.includes('User') || error.message.includes('user')
}
if (errorIncludesUserWord) {
onUserReject?.()
}
})
.then(async (receipt) => {
if (pendingExecutionKey) {

View File

@ -71,6 +71,7 @@ type OwnProps = {
ethBalance: string
onCancel: () => void
onUserConfirm: (safeTxHash: string) => void
onUserTxReject: () => void
onClose: () => void
}
@ -84,6 +85,7 @@ const ConfirmTransactionModal = ({
onCancel,
onUserConfirm,
onClose,
onUserTxReject,
}: OwnProps): React.ReactElement | null => {
const dispatch = useDispatch()
if (!isOpen) {
@ -111,6 +113,7 @@ const ConfirmTransactionModal = ({
navigateToTransactionsTab: false,
},
handleUserConfirmation,
onUserTxReject,
),
)
onClose()
@ -133,27 +136,25 @@ const ConfirmTransactionModal = ({
<>
<AddressInfo ethBalance={ethBalance} safeAddress={safeAddress} safeName={safeName} />
<DividerLine withArrow />
{txs.map((tx, index) => {
return (
<Wrapper key={index}>
<Collapse description={<AddressInfo safeAddress={tx.to} />} title={`Transaction ${index + 1}`}>
<CollapseContent>
<div className="section">
<Heading tag="h3">Value</Heading>
<div className="value-section">
<Img alt="Ether" height={40} src={getEthAsToken('0').logoUri} />
<Bold>{humanReadableValue(tx.value, 18)} ETH</Bold>
</div>
{txs.map((tx, index) => (
<Wrapper key={index}>
<Collapse description={<AddressInfo safeAddress={tx.to} />} title={`Transaction ${index + 1}`}>
<CollapseContent>
<div className="section">
<Heading tag="h3">Value</Heading>
<div className="value-section">
<Img alt="Ether" height={40} src={getEthAsToken('0').logoUri} />
<Bold>{humanReadableValue(tx.value, 18)} ETH</Bold>
</div>
<div className="section">
<Heading tag="h3">Data (hex encoded)*</Heading>
<StyledTextBox>{tx.data}</StyledTextBox>
</div>
</CollapseContent>
</Collapse>
</Wrapper>
)
})}
</div>
<div className="section">
<Heading tag="h3">Data (hex encoded)*</Heading>
<StyledTextBox>{tx.data}</StyledTextBox>
</div>
</CollapseContent>
</Collapse>
</Wrapper>
))}
</>
)

View File

@ -8,6 +8,7 @@ import {
INTERFACE_MESSAGES,
RequestId,
Transaction,
LowercaseNetworks,
} from '@gnosis.pm/safe-apps-sdk'
import { useDispatch, useSelector } from 'react-redux'
import { useEffect, useCallback, MutableRefObject } from 'react'
@ -88,7 +89,7 @@ const useIframeMessageHandler = (
messageId: INTERFACE_MESSAGES.ON_SAFE_INFO,
data: {
safeAddress: safeAddress as string,
network,
network: network.toLowerCase() as LowercaseNetworks,
ethBalance: ethBalance as string,
},
}

View File

@ -1,5 +1,5 @@
import React, { useCallback, useEffect, useRef, useState, useMemo } from 'react'
import { INTERFACE_MESSAGES, Transaction, RequestId } from '@gnosis.pm/safe-apps-sdk'
import { INTERFACE_MESSAGES, Transaction, RequestId, LowercaseNetworks } from '@gnosis.pm/safe-apps-sdk'
import { Card, IconText, Loader, Menu, Title } from '@gnosis.pm/safe-react-components'
import { useSelector } from 'react-redux'
import styled, { css } from 'styled-components'
@ -102,6 +102,13 @@ const Apps = (): React.ReactElement => {
)
}
const onUserTxReject = () => {
sendMessageToIframe(
{ messageId: INTERFACE_MESSAGES.TRANSACTION_REJECTED, data: {} },
confirmTransactionModal.requestId,
)
}
const onSelectApp = useCallback(
(appId) => {
if (selectedAppId === appId) {
@ -148,7 +155,7 @@ const Apps = (): React.ReactElement => {
messageId: INTERFACE_MESSAGES.ON_SAFE_INFO,
data: {
safeAddress: safeAddress as string,
network,
network: network.toLowerCase() as LowercaseNetworks,
ethBalance: ethBalance as string,
},
})
@ -208,6 +215,7 @@ const Apps = (): React.ReactElement => {
onCancel={closeConfirmationModal}
onClose={closeConfirmationModal}
onUserConfirm={onUserTxConfirm}
onUserTxReject={onUserTxReject}
/>
</>
)

896
yarn.lock

File diff suppressed because it is too large Load Diff