Merge branch 'development' of https://github.com/gnosis/safe-react into 1013-undefined-error
This commit is contained in:
commit
fe7e4b5536
|
@ -214,6 +214,7 @@
|
||||||
"@types/node": "14.0.12",
|
"@types/node": "14.0.12",
|
||||||
"@types/react": "^16.9.32",
|
"@types/react": "^16.9.32",
|
||||||
"@types/react-dom": "^16.9.6",
|
"@types/react-dom": "^16.9.6",
|
||||||
|
"@types/styled-components": "^5.1.0",
|
||||||
"@typescript-eslint/eslint-plugin": "3.2.0",
|
"@typescript-eslint/eslint-plugin": "3.2.0",
|
||||||
"@typescript-eslint/parser": "3.2.0",
|
"@typescript-eslint/parser": "3.2.0",
|
||||||
"autoprefixer": "9.8.0",
|
"autoprefixer": "9.8.0",
|
||||||
|
@ -239,6 +240,7 @@
|
||||||
"truffle": "5.1.29",
|
"truffle": "5.1.29",
|
||||||
"typescript": "^3.9.5",
|
"typescript": "^3.9.5",
|
||||||
"wait-on": "5.0.1",
|
"wait-on": "5.0.1",
|
||||||
|
"web3-eth-contract": "^1.2.9",
|
||||||
"web3-utils": "^1.2.8"
|
"web3-utils": "^1.2.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ const devConfig = {
|
||||||
[SIGNATURES_VIA_METAMASK]: false,
|
[SIGNATURES_VIA_METAMASK]: false,
|
||||||
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
[RELAY_API_URL]: 'https://safe-relay.staging.gnosisdev.com/api/v1/',
|
||||||
[SAFE_APPS_URL]: 'https://safe-apps.dev.gnosisdev.com/'
|
[SAFE_APPS_URL]: 'https://safe-apps.dev.gnosisdev.com/'
|
||||||
|
//[SAFE_APPS_URL]: 'http://localhost:3002/'
|
||||||
}
|
}
|
||||||
|
|
||||||
export default devConfig
|
export default devConfig
|
||||||
|
|
|
@ -8,7 +8,7 @@ export interface AbiItemExtended extends AbiItem {
|
||||||
signatureHash: string
|
signatureHash: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getMethodSignature = ({ inputs, name }: AbiItem) => {
|
export const getMethodSignature = ({ inputs, name }: AbiItem): string => {
|
||||||
const params = inputs.map((x) => x.type).join(',')
|
const params = inputs.map((x) => x.type).join(',')
|
||||||
return `${name}(${params})`
|
return `${name}(${params})`
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@ const createERC721TokenContract = async () => {
|
||||||
const web3 = getWeb3()
|
const web3 = getWeb3()
|
||||||
const erc721Token = await contract(ERC721)
|
const erc721Token = await contract(ERC721)
|
||||||
erc721Token.setProvider(web3.currentProvider)
|
erc721Token.setProvider(web3.currentProvider)
|
||||||
|
|
||||||
return erc721Token
|
return erc721Token
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
|
import memoize from 'lodash.memoize'
|
||||||
import logo from 'src/assets/icons/icon_etherTokens.svg'
|
import logo from 'src/assets/icons/icon_etherTokens.svg'
|
||||||
import generateBatchRequests from 'src/logic/contracts/generateBatchRequests'
|
import generateBatchRequests from 'src/logic/contracts/generateBatchRequests'
|
||||||
import { getStandardTokenContract, getTokenInfos } from 'src/logic/tokens/store/actions/fetchTokens'
|
import {
|
||||||
|
getStandardTokenContract,
|
||||||
|
getTokenInfos,
|
||||||
|
getERC721TokenContract,
|
||||||
|
} from 'src/logic/tokens/store/actions/fetchTokens'
|
||||||
import { makeToken, Token } from 'src/logic/tokens/store/model/token'
|
import { makeToken, Token } from 'src/logic/tokens/store/model/token'
|
||||||
import { ALTERNATIVE_TOKEN_ABI } from 'src/logic/tokens/utils/alternativeAbi'
|
import { ALTERNATIVE_TOKEN_ABI } from 'src/logic/tokens/utils/alternativeAbi'
|
||||||
import { web3ReadOnly as web3 } from 'src/logic/wallets/getWeb3'
|
import { web3ReadOnly as web3 } from 'src/logic/wallets/getWeb3'
|
||||||
|
@ -46,6 +51,14 @@ export const isSendERC721Transaction = (tx: any, txCode: string, knownTokens: an
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getERC721Symbol = memoize(
|
||||||
|
async (contractAddress: string): Promise<string> => {
|
||||||
|
const ERC721token = await getERC721TokenContract()
|
||||||
|
const tokenInstance = await ERC721token.at(contractAddress)
|
||||||
|
return tokenInstance.symbol()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
export const getERC20DecimalsAndSymbol = async (
|
export const getERC20DecimalsAndSymbol = async (
|
||||||
tokenAddress: string,
|
tokenAddress: string,
|
||||||
): Promise<{ decimals: number; symbol: string }> => {
|
): Promise<{ decimals: number; symbol: string }> => {
|
||||||
|
|
|
@ -48,6 +48,7 @@ const wallets = [
|
||||||
{ walletName: 'torus', desktop: true },
|
{ walletName: 'torus', desktop: true },
|
||||||
{ walletName: 'unilogin', desktop: true },
|
{ walletName: 'unilogin', desktop: true },
|
||||||
{ walletName: 'coinbase', desktop: false },
|
{ walletName: 'coinbase', desktop: false },
|
||||||
|
{ walletName: 'walletLink', rpcUrl: infuraUrl, desktop: false },
|
||||||
{ walletName: 'opera', desktop: false },
|
{ walletName: 'opera', desktop: false },
|
||||||
{ walletName: 'operaTouch', desktop: false },
|
{ walletName: 'operaTouch', desktop: false },
|
||||||
]
|
]
|
||||||
|
|
|
@ -145,6 +145,8 @@ const AddAppForm = ({ appList, formId, closeModal, onAppAdded, setIsSubmitDisabl
|
||||||
onAppAdded(appInfo)
|
onAppAdded(appInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onTextFieldChange = () => {}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GnoForm
|
<GnoForm
|
||||||
initialValues={{
|
initialValues={{
|
||||||
|
@ -169,7 +171,7 @@ const AddAppForm = ({ appList, formId, closeModal, onAppAdded, setIsSubmitDisabl
|
||||||
|
|
||||||
<AppInfo>
|
<AppInfo>
|
||||||
<Img alt="Token image" height={55} src={appInfo.iconUrl} />
|
<Img alt="Token image" height={55} src={appInfo.iconUrl} />
|
||||||
<StyledTextFileAppName label="App name" readOnly value={appInfo.name} />
|
<StyledTextFileAppName label="App name" readOnly value={appInfo.name} onChange={onTextFieldChange} />
|
||||||
</AppInfo>
|
</AppInfo>
|
||||||
|
|
||||||
<FormSpy
|
<FormSpy
|
||||||
|
|
|
@ -38,6 +38,21 @@ const Centered = styled.div`
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const IframeWrapper = styled.div`
|
||||||
|
position: relative;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
`
|
||||||
|
|
||||||
|
const IframeCoverLoading = styled.div`
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background: white;
|
||||||
|
`
|
||||||
const operations = {
|
const operations = {
|
||||||
SEND_TRANSACTIONS: 'SEND_TRANSACTIONS',
|
SEND_TRANSACTIONS: 'SEND_TRANSACTIONS',
|
||||||
ON_SAFE_INFO: 'ON_SAFE_INFO',
|
ON_SAFE_INFO: 'ON_SAFE_INFO',
|
||||||
|
@ -133,17 +148,14 @@ function Apps({ closeModal, closeSnackbar, enqueueSnackbar, openModal }) {
|
||||||
const app = getSelectedApp()
|
const app = getSelectedApp()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<IframeWrapper>
|
||||||
{appIsLoading && <Loader size="md" />}
|
{appIsLoading && (
|
||||||
<StyledIframe
|
<IframeCoverLoading>
|
||||||
frameBorder="0"
|
<Loader size="md" />
|
||||||
id={`iframe-${app.name}`}
|
</IframeCoverLoading>
|
||||||
ref={iframeRef}
|
)}
|
||||||
shouldDisplay={!appIsLoading}
|
<StyledIframe frameBorder="0" id={`iframe-${app.name}`} ref={iframeRef} src={app.url} title={app.name} />
|
||||||
src={app.url}
|
</IframeWrapper>
|
||||||
title={app.name}
|
|
||||||
/>
|
|
||||||
</>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
import TextareaField from 'src/components/forms/TextareaField'
|
||||||
|
import {
|
||||||
|
isAddress,
|
||||||
|
isBoolean,
|
||||||
|
isByte,
|
||||||
|
isInt,
|
||||||
|
isUint,
|
||||||
|
} from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils'
|
||||||
|
|
||||||
|
const validator = (value: string): string | undefined => {
|
||||||
|
try {
|
||||||
|
const values = JSON.parse(value)
|
||||||
|
|
||||||
|
if (!Array.isArray(values)) {
|
||||||
|
return 'be sure to surround value with []'
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
return 'invalid format'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const typePlaceholder = (text: string, type: string): string => {
|
||||||
|
if (isAddress(type)) {
|
||||||
|
return `${text} E.g.: ["0xACa94ef8bD5ffEE41947b4585a84BdA5a3d3DA6E","0x1dF62f291b2E969fB0849d99D9Ce41e2F137006e"]`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isBoolean(type)) {
|
||||||
|
return `${text} E.g.: [true, false, false, true]`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUint(type)) {
|
||||||
|
return `${text} E.g.: [1000, 212, 320000022, 23]`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isInt(type)) {
|
||||||
|
return `${text} E.g.: [1000, -212, 1232, -1]`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isByte(type)) {
|
||||||
|
return `${text} E.g.: ["0xc00000000000000000000000000000000000", "0xc00000000000000000000000000000000001"]`
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${text} E.g.: ["first value", "second value", "third value"]`
|
||||||
|
}
|
||||||
|
|
||||||
|
const ArrayTypeInput = ({ name, text, type }: { name: string; text: string; type: string }): JSX.Element => (
|
||||||
|
<TextareaField name={name} placeholder={typePlaceholder(text, type)} text={text} type="text" validate={validator} />
|
||||||
|
)
|
||||||
|
|
||||||
|
export default ArrayTypeInput
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Checkbox } from '@gnosis.pm/safe-react-components'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import Col from 'src/components/layout/Col'
|
import Col from 'src/components/layout/Col'
|
||||||
|
@ -5,7 +6,8 @@ import Field from 'src/components/forms/Field'
|
||||||
import TextField from 'src/components/forms/TextField'
|
import TextField from 'src/components/forms/TextField'
|
||||||
|
|
||||||
import { composeValidators, mustBeEthereumAddress, required } from 'src/components/forms/validator'
|
import { composeValidators, mustBeEthereumAddress, required } from 'src/components/forms/validator'
|
||||||
import { Checkbox } from '@gnosis.pm/safe-react-components'
|
import { isArrayParameter } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/utils'
|
||||||
|
import ArrayTypeInput from './ArrayTypeInput'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
type: string
|
type: string
|
||||||
|
@ -13,10 +15,11 @@ type Props = {
|
||||||
placeholder: string
|
placeholder: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const InputComponent = ({ type, keyValue, placeholder }: Props) => {
|
const InputComponent = ({ type, keyValue, placeholder }: Props): JSX.Element => {
|
||||||
if (!type) {
|
if (!type) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'bool': {
|
case 'bool': {
|
||||||
const inputProps = {
|
const inputProps = {
|
||||||
|
@ -46,15 +49,19 @@ const InputComponent = ({ type, keyValue, placeholder }: Props) => {
|
||||||
default: {
|
default: {
|
||||||
return (
|
return (
|
||||||
<Col>
|
<Col>
|
||||||
<Field
|
{isArrayParameter(type) ? (
|
||||||
component={TextField}
|
<ArrayTypeInput name={keyValue} text={placeholder} type={type} />
|
||||||
name={keyValue}
|
) : (
|
||||||
placeholder={placeholder}
|
<Field
|
||||||
testId={keyValue}
|
component={TextField}
|
||||||
text={placeholder}
|
name={keyValue}
|
||||||
type="text"
|
placeholder={placeholder}
|
||||||
validate={required}
|
testId={keyValue}
|
||||||
/>
|
text={placeholder}
|
||||||
|
type="text"
|
||||||
|
validate={required}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,28 +4,32 @@ import { useField } from 'react-final-form'
|
||||||
import Row from 'src/components/layout/Row'
|
import Row from 'src/components/layout/Row'
|
||||||
|
|
||||||
import InputComponent from './InputComponent'
|
import InputComponent from './InputComponent'
|
||||||
|
import { generateFormFieldKey } from '../utils'
|
||||||
|
import { AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService'
|
||||||
|
|
||||||
const RenderInputParams = () => {
|
const RenderInputParams = (): JSX.Element => {
|
||||||
const {
|
const {
|
||||||
meta: { valid: validABI },
|
meta: { valid: validABI },
|
||||||
} = useField('abi', { subscription: { valid: true, value: true } })
|
} = useField('abi', { subscription: { valid: true, value: true } })
|
||||||
const {
|
const {
|
||||||
input: { value: method },
|
input: { value: method },
|
||||||
}: any = useField('selectedMethod', { subscription: { value: true } })
|
}: { input: { value: AbiItemExtended } } = useField('selectedMethod', { subscription: { value: true } })
|
||||||
const renderInputs = validABI && !!method && method.inputs.length
|
const renderInputs = validABI && !!method && method.inputs.length
|
||||||
|
|
||||||
return !renderInputs
|
return !renderInputs ? null : (
|
||||||
? null
|
<>
|
||||||
: method.inputs.map(({ name, type }, index) => {
|
{method.inputs.map(({ name, type }, index) => {
|
||||||
const placeholder = name ? `${name} (${type})` : type
|
const placeholder = name ? `${name} (${type})` : type
|
||||||
const key = `methodInput-${method.name}_${index}_${type}`
|
const key = generateFormFieldKey(type, method.signatureHash, index)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Row key={key} margin="sm">
|
<Row key={key} margin="sm">
|
||||||
<InputComponent type={type} keyValue={key} placeholder={placeholder} />
|
<InputComponent type={type} keyValue={key} placeholder={placeholder} />
|
||||||
</Row>
|
</Row>
|
||||||
)
|
)
|
||||||
})
|
})}
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default RenderInputParams
|
export default RenderInputParams
|
||||||
|
|
|
@ -22,7 +22,7 @@ import Header from 'src/routes/safe/components/Balances/SendModal/screens/Contra
|
||||||
import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils'
|
import { setImageToPlaceholder } from 'src/routes/safe/components/Balances/utils'
|
||||||
import createTransaction from 'src/routes/safe/store/actions/createTransaction'
|
import createTransaction from 'src/routes/safe/store/actions/createTransaction'
|
||||||
import { safeSelector } from 'src/routes/safe/store/selectors'
|
import { safeSelector } from 'src/routes/safe/store/selectors'
|
||||||
import { getValueFromTxInputs } from '../utils'
|
import { generateFormFieldKey, getValueFromTxInputs } from '../utils'
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ const ContractInteractionReview = ({ onClose, onPrev, tx }: Props) => {
|
||||||
</Paragraph>
|
</Paragraph>
|
||||||
</Row>
|
</Row>
|
||||||
{tx.selectedMethod.inputs.map(({ name, type }, index) => {
|
{tx.selectedMethod.inputs.map(({ name, type }, index) => {
|
||||||
const key = `methodInput-${tx.selectedMethod.name}_${index}_${type}`
|
const key = generateFormFieldKey(type, tx.selectedMethod.signatureHash, index)
|
||||||
const value: string = getValueFromTxInputs(key, type, tx)
|
const value: string = getValueFromTxInputs(key, type, tx)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { FORM_ERROR } from 'final-form'
|
import { FORM_ERROR, Mutator, SubmissionErrors } from 'final-form'
|
||||||
import createDecorator from 'final-form-calculate'
|
import createDecorator from 'final-form-calculate'
|
||||||
import { AbiItem } from 'web3-utils'
|
import { ContractSendMethod } from 'web3-eth-contract'
|
||||||
|
|
||||||
import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator'
|
import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator'
|
||||||
import { getNetwork } from 'src/config'
|
import { getNetwork } from 'src/config'
|
||||||
import { getConfiguredSource } from 'src/logic/contractInteraction/sources'
|
import { getConfiguredSource } from 'src/logic/contractInteraction/sources'
|
||||||
import { AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService'
|
import { AbiItemExtended } from 'src/logic/contractInteraction/sources/ABIService'
|
||||||
import { getAddressFromENS, getWeb3 } from 'src/logic/wallets/getWeb3'
|
import { getAddressFromENS, getWeb3 } from 'src/logic/wallets/getWeb3'
|
||||||
import { TransactionReviewType } from '../Review'
|
import { TransactionReviewType } from 'src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/Review'
|
||||||
import { isValidEnsName } from 'src/logic/wallets/ethAddresses'
|
import { isValidEnsName } from 'src/logic/wallets/ethAddresses'
|
||||||
|
|
||||||
export const NO_CONTRACT = 'no contract'
|
export const NO_CONTRACT = 'no contract'
|
||||||
|
@ -50,7 +50,7 @@ export const ensResolver = createDecorator({
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
export const formMutators = {
|
export const formMutators: Record<string, Mutator<{ selectedMethod: { name: string } }>> = {
|
||||||
setMax: (args, state, utils) => {
|
setMax: (args, state, utils) => {
|
||||||
utils.changeValue(state, 'value', () => args[0])
|
utils.changeValue(state, 'value', () => args[0])
|
||||||
},
|
},
|
||||||
|
@ -73,7 +73,16 @@ export const formMutators = {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
export const handleSubmitError = (error, values) => {
|
export const isAddress = (type: string): boolean => type.indexOf('address') === 0
|
||||||
|
export const isBoolean = (type: string): boolean => type.indexOf('bool') === 0
|
||||||
|
export const isString = (type: string): boolean => type.indexOf('string') === 0
|
||||||
|
export const isUint = (type: string): boolean => type.indexOf('uint') === 0
|
||||||
|
export const isInt = (type: string): boolean => type.indexOf('int') === 0
|
||||||
|
export const isByte = (type: string): boolean => type.indexOf('byte') === 0
|
||||||
|
|
||||||
|
export const isArrayParameter = (parameter: string): boolean => /(\[\d*])+$/.test(parameter)
|
||||||
|
|
||||||
|
export const handleSubmitError = (error: SubmissionErrors, values: Record<string, string>): Record<string, string> => {
|
||||||
for (const key in values) {
|
for (const key in values) {
|
||||||
if (values.hasOwnProperty(key) && values[key] === error.value) {
|
if (values.hasOwnProperty(key) && values[key] === error.value) {
|
||||||
return { [key]: error.reason }
|
return { [key]: error.reason }
|
||||||
|
@ -84,11 +93,30 @@ export const handleSubmitError = (error, values) => {
|
||||||
return { [FORM_ERROR]: error.message }
|
return { [FORM_ERROR]: error.message }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const createTxObject = (method: AbiItem, contractAddress: string, values) => {
|
export const generateFormFieldKey = (type: string, signatureHash: string, index: number): string => {
|
||||||
|
const keyType = isArrayParameter(type) ? 'arrayParam' : type
|
||||||
|
return `methodInput-${signatureHash}_${index}_${keyType}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const extractMethodArgs = (signatureHash: string, values: Record<string, string>) => ({ type }, index) => {
|
||||||
|
const key = generateFormFieldKey(type, signatureHash, index)
|
||||||
|
|
||||||
|
if (isArrayParameter(type)) {
|
||||||
|
return JSON.parse(values[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
return values[key]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createTxObject = (
|
||||||
|
method: AbiItemExtended,
|
||||||
|
contractAddress: string,
|
||||||
|
values: Record<string, string>,
|
||||||
|
): ContractSendMethod => {
|
||||||
const web3 = getWeb3()
|
const web3 = getWeb3()
|
||||||
const contract: any = new web3.eth.Contract([method], contractAddress)
|
const contract: any = new web3.eth.Contract([method], contractAddress)
|
||||||
const { inputs, name } = method
|
const { inputs, name, signatureHash } = method
|
||||||
const args = inputs.map(({ type }, index) => values[`methodInput-${name}_${index}_${type}`])
|
const args = inputs.map(extractMethodArgs(signatureHash, values))
|
||||||
|
|
||||||
return contract.methods[name](...args)
|
return contract.methods[name](...args)
|
||||||
}
|
}
|
||||||
|
@ -96,9 +124,15 @@ export const createTxObject = (method: AbiItem, contractAddress: string, values)
|
||||||
export const isReadMethod = (method: AbiItemExtended): boolean => method && method.action === 'read'
|
export const isReadMethod = (method: AbiItemExtended): boolean => method && method.action === 'read'
|
||||||
|
|
||||||
export const getValueFromTxInputs = (key: string, type: string, tx: TransactionReviewType): string => {
|
export const getValueFromTxInputs = (key: string, type: string, tx: TransactionReviewType): string => {
|
||||||
let value = tx[key]
|
if (isArrayParameter(type)) {
|
||||||
if (type === 'bool') {
|
key = key.replace('[]', '')
|
||||||
value = tx[key] ? String(tx[key]) : 'false'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let value = tx[key]
|
||||||
|
|
||||||
|
if (type === 'bool') {
|
||||||
|
value = String(value)
|
||||||
|
}
|
||||||
|
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ const ReviewCollectible = ({ closeSnackbar, enqueueSnackbar, onClose, onPrev, tx
|
||||||
const { fromWei, toBN } = getWeb3().utils
|
const { fromWei, toBN } = getWeb3().utils
|
||||||
|
|
||||||
const supportsSafeTransfer = await containsMethodByHash(tx.assetAddress, SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH)
|
const supportsSafeTransfer = await containsMethodByHash(tx.assetAddress, SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH)
|
||||||
const methodToCall = supportsSafeTransfer ? SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH : 'transfer'
|
const methodToCall = supportsSafeTransfer ? `0x${SAFE_TRANSFER_FROM_WITHOUT_DATA_HASH}` : 'transfer'
|
||||||
const transferParams = [tx.recipientAddress, tx.nftTokenId]
|
const transferParams = [tx.recipientAddress, tx.nftTokenId]
|
||||||
const params = methodToCall === 'transfer' ? transferParams : [safeAddress, ...transferParams]
|
const params = methodToCall === 'transfer' ? transferParams : [safeAddress, ...transferParams]
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,10 @@ export const getTxAmount = (tx, formatted = true) => {
|
||||||
const { decimals = 18, decodedParams, isTokenTransfer, symbol } = tx
|
const { decimals = 18, decodedParams, isTokenTransfer, symbol } = tx
|
||||||
const { value } = isTokenTransfer && !!decodedParams && !!decodedParams.transfer ? decodedParams.transfer : tx
|
const { value } = isTokenTransfer && !!decodedParams && !!decodedParams.transfer ? decodedParams.transfer : tx
|
||||||
|
|
||||||
|
if (tx.isCollectibleTransfer) {
|
||||||
|
return `1 ${tx.symbol}`
|
||||||
|
}
|
||||||
|
|
||||||
if (!isTokenTransfer && !(Number(value) > 0)) {
|
if (!isTokenTransfer && !(Number(value) > 0)) {
|
||||||
return NOT_AVAILABLE
|
return NOT_AVAILABLE
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { DecodedMethods, decodeMethods } from 'src/logic/contracts/methodIds'
|
||||||
import { TOKEN_REDUCER_ID } from 'src/logic/tokens/store/reducer/tokens'
|
import { TOKEN_REDUCER_ID } from 'src/logic/tokens/store/reducer/tokens'
|
||||||
import {
|
import {
|
||||||
getERC20DecimalsAndSymbol,
|
getERC20DecimalsAndSymbol,
|
||||||
|
getERC721Symbol,
|
||||||
isSendERC20Transaction,
|
isSendERC20Transaction,
|
||||||
isSendERC721Transaction,
|
isSendERC721Transaction,
|
||||||
} from 'src/logic/tokens/utils/tokenHelpers'
|
} from 'src/logic/tokens/utils/tokenHelpers'
|
||||||
|
@ -285,7 +286,7 @@ export const buildTx = async ({
|
||||||
safeTxGas: tx.safeTxGas,
|
safeTxGas: tx.safeTxGas,
|
||||||
safeTxHash: tx.safeTxHash,
|
safeTxHash: tx.safeTxHash,
|
||||||
submissionDate: tx.submissionDate,
|
submissionDate: tx.submissionDate,
|
||||||
symbol,
|
symbol: isSendERC721Tx ? await getERC721Symbol(tx.to) : symbol,
|
||||||
upgradeTx: isUpgradeTx,
|
upgradeTx: isUpgradeTx,
|
||||||
value: tx.value.toString(),
|
value: tx.value.toString(),
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue