(Refactor) Update `dataDecoded` structure (#995)
This commit is contained in:
parent
509aefe286
commit
41ec0786b7
|
@ -57,6 +57,7 @@ type TokenMethods = 'transfer' | 'transferFrom' | 'safeTransferFrom'
|
|||
|
||||
type DecodedValues = Array<{
|
||||
name: string
|
||||
type?: string
|
||||
value: string
|
||||
}>
|
||||
|
||||
|
@ -70,7 +71,12 @@ type TokenDecodedParams = {
|
|||
|
||||
export type DecodedMethods = SafeDecodedParams | TokenDecodedParams | null
|
||||
|
||||
export const decodeParamsFromSafeMethod = (data: string): SafeDecodedParams | null => {
|
||||
export interface DataDecoded {
|
||||
method: SafeMethods | TokenMethods
|
||||
parameters: DecodedValues
|
||||
}
|
||||
|
||||
export const decodeParamsFromSafeMethod = (data: string): DataDecoded | null => {
|
||||
const [methodId, params] = [data.slice(0, 10) as keyof typeof METHOD_TO_ID | string, data.slice(10)]
|
||||
|
||||
switch (methodId) {
|
||||
|
@ -78,10 +84,11 @@ export const decodeParamsFromSafeMethod = (data: string): SafeDecodedParams | nu
|
|||
case '0xe318b52b': {
|
||||
const decodedParameters = web3.eth.abi.decodeParameters(['uint', 'address', 'address'], params)
|
||||
return {
|
||||
[METHOD_TO_ID[methodId]]: [
|
||||
method: METHOD_TO_ID[methodId],
|
||||
parameters: [
|
||||
{ name: 'oldOwner', value: decodedParameters[1] },
|
||||
{ name: 'newOwner', value: decodedParameters[2] },
|
||||
]
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,10 +96,11 @@ export const decodeParamsFromSafeMethod = (data: string): SafeDecodedParams | nu
|
|||
case '0x0d582f13': {
|
||||
const decodedParameters = web3.eth.abi.decodeParameters(['address', 'uint'], params)
|
||||
return {
|
||||
[METHOD_TO_ID[methodId]]: [
|
||||
method: METHOD_TO_ID[methodId],
|
||||
parameters: [
|
||||
{ name: 'owner', value: decodedParameters[0] },
|
||||
{ name: '_threshold', value: decodedParameters[1] },
|
||||
]
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,10 +108,11 @@ export const decodeParamsFromSafeMethod = (data: string): SafeDecodedParams | nu
|
|||
case '0xf8dc5dd9': {
|
||||
const decodedParameters = web3.eth.abi.decodeParameters(['address', 'address', 'uint'], params)
|
||||
return {
|
||||
[METHOD_TO_ID[methodId]]: [
|
||||
method: METHOD_TO_ID[methodId],
|
||||
parameters: [
|
||||
{ name: 'oldOwner', value: decodedParameters[1] },
|
||||
{ name: '_threshold', value: decodedParameters[2] },
|
||||
]
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,9 +120,10 @@ export const decodeParamsFromSafeMethod = (data: string): SafeDecodedParams | nu
|
|||
case '0x694e80c3': {
|
||||
const decodedParameters = web3.eth.abi.decodeParameters(['uint'], params)
|
||||
return {
|
||||
[METHOD_TO_ID[methodId]]: [
|
||||
method: METHOD_TO_ID[methodId],
|
||||
parameters: [
|
||||
{ name: '_threshold', value: decodedParameters[0] },
|
||||
]
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,7 +136,7 @@ const isSafeMethod = (methodId: string): boolean => {
|
|||
return !!METHOD_TO_ID[methodId]
|
||||
}
|
||||
|
||||
export const decodeMethods = (data: string): DecodedMethods => {
|
||||
export const decodeMethods = (data: string): DataDecoded | null => {
|
||||
const [methodId, params] = [data.slice(0, 10), data.slice(10)]
|
||||
|
||||
if (isSafeMethod(methodId)) {
|
||||
|
@ -138,10 +148,11 @@ export const decodeMethods = (data: string): DecodedMethods => {
|
|||
case '0xa9059cbb': {
|
||||
const decodeParameters = web3.eth.abi.decodeParameters(['address', 'uint'], params)
|
||||
return {
|
||||
transfer: [
|
||||
method: 'transfer',
|
||||
parameters: [
|
||||
{ name: 'to', value: decodeParameters[0] },
|
||||
{ name: 'value', value: decodeParameters[1] },
|
||||
]
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,23 +160,25 @@ export const decodeMethods = (data: string): DecodedMethods => {
|
|||
case '0x23b872dd': {
|
||||
const decodeParameters = web3.eth.abi.decodeParameters(['address', 'address', 'uint'], params)
|
||||
return {
|
||||
transferFrom: [
|
||||
method: 'transferFrom',
|
||||
parameters: [
|
||||
{ name: 'from', value: decodeParameters[0] },
|
||||
{ name: 'to', value: decodeParameters[1] },
|
||||
{ name: 'value', value: decodeParameters[2] },
|
||||
]
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
// 42842e0e - safeTransferFrom(address,address,uint256)
|
||||
case '0x42842e0e':{
|
||||
case '0x42842e0e': {
|
||||
const decodedParameters = web3.eth.abi.decodeParameters(['address', 'address', 'uint'], params)
|
||||
return {
|
||||
safeTransferFrom: [
|
||||
method: 'safeTransferFrom',
|
||||
parameters: [
|
||||
{ name: 'from', value: decodedParameters[0] },
|
||||
{ name: 'to', value: decodedParameters[1] },
|
||||
{ name: 'value', value: decodedParameters[2] },
|
||||
]
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import { loadCurrencyValues } from 'src/logic/currencyValues/store/utils/currenc
|
|||
|
||||
export const fetchCurrencyValues = (safeAddress: string) => async (dispatch) => {
|
||||
try {
|
||||
const storedCurrencies: Map<string, CurrencyRateValue> | {} = await loadCurrencyValues()
|
||||
const storedCurrencies: Map<string, CurrencyRateValue> | any = await loadCurrencyValues()
|
||||
const storedCurrency = storedCurrencies[safeAddress]
|
||||
if (!storedCurrency) {
|
||||
return batch(() => {
|
||||
|
|
|
@ -11,6 +11,6 @@ export const saveCurrencyValues = async (currencyValues: Map<string, CurrencyRat
|
|||
}
|
||||
}
|
||||
|
||||
export const loadCurrencyValues = async (): Promise<Map<string, CurrencyRateValue> | {}> => {
|
||||
export const loadCurrencyValues = async (): Promise<Map<string, CurrencyRateValue> | any> => {
|
||||
return (await loadFromStorage(CURRENCY_VALUES_STORAGE_KEY)) || {}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json'
|
||||
|
||||
import { getWeb3 } from 'src/logic/wallets/getWeb3'
|
||||
import { TxArgs } from 'src/routes/safe/store/models/types/transaction'
|
||||
|
||||
export const CALL = 0
|
||||
export const DELEGATE_CALL = 1
|
||||
|
@ -20,7 +21,7 @@ export const getApprovalTransaction = async ({
|
|||
sender,
|
||||
to,
|
||||
valueInWei,
|
||||
}) => {
|
||||
}: TxArgs) => {
|
||||
const txHash = await safeInstance.getTransactionHash(
|
||||
to,
|
||||
valueInWei,
|
||||
|
@ -61,7 +62,7 @@ export const getExecutionTransaction = async ({
|
|||
sigs,
|
||||
to,
|
||||
valueInWei,
|
||||
}) => {
|
||||
}: TxArgs) => {
|
||||
try {
|
||||
const web3 = getWeb3()
|
||||
const contract: any = new web3.eth.Contract(GnosisSafeSol.abi as any, safeInstance.address)
|
||||
|
|
|
@ -1,6 +1,16 @@
|
|||
import { Record } from 'immutable'
|
||||
import { Record, RecordOf } from 'immutable'
|
||||
|
||||
export const makeProvider = Record({
|
||||
export type ProviderProps = {
|
||||
name: string
|
||||
loaded: boolean
|
||||
available: boolean
|
||||
account: string
|
||||
network: number
|
||||
smartContractWallet: boolean
|
||||
hardwareWallet: boolean
|
||||
}
|
||||
|
||||
export const makeProvider = Record<ProviderProps>({
|
||||
name: '',
|
||||
loaded: false,
|
||||
available: false,
|
||||
|
@ -10,4 +20,6 @@ export const makeProvider = Record({
|
|||
hardwareWallet: false,
|
||||
})
|
||||
|
||||
// Useage const someProvider: Provider = makeProvider({ name: 'METAMASK', loaded: false, available: false })
|
||||
// Usage const someProvider: Provider = makeProvider({ name: 'METAMASK', loaded: false, available: false })
|
||||
|
||||
export type ProviderRecord = RecordOf<ProviderProps>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React from 'react'
|
||||
import React, { SyntheticEvent } from 'react'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import Button from 'src/components/layout/Button'
|
||||
|
@ -36,14 +36,20 @@ export const ContinueFooter = ({
|
|||
onContinue,
|
||||
}: {
|
||||
continueButtonDisabled: boolean
|
||||
onContinue: () => void
|
||||
onContinue: (event: SyntheticEvent) => void
|
||||
}) => (
|
||||
<Button color="primary" disabled={continueButtonDisabled} onClick={onContinue} variant="contained">
|
||||
Continue
|
||||
</Button>
|
||||
)
|
||||
|
||||
export const ErrorFooter = ({ onCancel, onRetry }: { onCancel: () => void; onRetry: () => void }) => (
|
||||
export const ErrorFooter = ({
|
||||
onCancel,
|
||||
onRetry,
|
||||
}: {
|
||||
onCancel: (event: SyntheticEvent) => void
|
||||
onRetry: (event: SyntheticEvent) => void
|
||||
}) => (
|
||||
<>
|
||||
<ButtonWithMargin onClick={onCancel} variant="contained">
|
||||
Cancel
|
||||
|
|
|
@ -102,7 +102,7 @@ const curriedSafeAppValidator = memoize((appList) => async (value: string) => {
|
|||
}
|
||||
})
|
||||
|
||||
const composeValidatorsApps = (...validators: Function[]) => (value, values, meta) => {
|
||||
const composeValidatorsApps = (...validators) => (value, values, meta) => {
|
||||
if (!meta.modified) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -19,13 +19,14 @@ import MethodsDropdown from './MethodsDropdown'
|
|||
import RenderInputParams from './RenderInputParams'
|
||||
import RenderOutputParams from './RenderOutputParams'
|
||||
import { abiExtractor, createTxObject, formMutators, handleSubmitError, isReadMethod, ensResolver } from './utils'
|
||||
import { TransactionReviewType } from './Review'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
export interface CreatedTx {
|
||||
contractAddress: string
|
||||
data: string
|
||||
selectedMethod: any
|
||||
selectedMethod: TransactionReviewType
|
||||
value: string | number
|
||||
}
|
||||
|
||||
|
|
|
@ -34,10 +34,10 @@ const AddressBookTable = React.lazy(() => import('src/routes/safe/components/Add
|
|||
interface Props {
|
||||
sendFunds: Record<string, any>
|
||||
showReceive: boolean
|
||||
onShow: Function
|
||||
onHide: Function
|
||||
showSendFunds: Function
|
||||
hideSendFunds: Function
|
||||
onShow: (value: string) => void
|
||||
onHide: (value: string) => void
|
||||
showSendFunds: (value: string) => void
|
||||
hideSendFunds: () => void
|
||||
match: Record<string, any>
|
||||
location: Record<string, any>
|
||||
history: Record<string, any>
|
||||
|
|
|
@ -51,6 +51,11 @@ export const getTxData = (tx) => {
|
|||
txData.addedOwner = newOwner
|
||||
}
|
||||
}
|
||||
if (tx.multiSendTx) {
|
||||
txData.recipient = tx.recipient
|
||||
txData.data = tx.data
|
||||
txData.customTx = true
|
||||
}
|
||||
} else if (tx.customTx) {
|
||||
txData.recipient = tx.recipient
|
||||
txData.data = tx.data
|
||||
|
|
|
@ -27,13 +27,14 @@ import { removeTransaction } from 'src/routes/safe/store/actions/transactions/re
|
|||
import {
|
||||
generateSafeTxHash,
|
||||
mockTransaction,
|
||||
TxToMock,
|
||||
} from 'src/routes/safe/store/actions/transactions/utils/transactionHelpers'
|
||||
import { getLastTx, getNewTxNonce, shouldExecuteTransaction } from 'src/routes/safe/store/actions/utils'
|
||||
import { getErrorMessage } from 'src/test/utils/ethereumErrors'
|
||||
import { makeConfirmation } from '../models/confirmation'
|
||||
import fetchTransactions from './transactions/fetchTransactions'
|
||||
import { safeTransactionsSelector } from 'src/routes/safe/store/selectors'
|
||||
import { TransactionStatus } from 'src/routes/safe/store/models/types/transaction'
|
||||
import { TransactionStatus, TxArgs } from 'src/routes/safe/store/models/types/transaction'
|
||||
|
||||
export const removeTxFromStore = (tx, safeAddress, dispatch, state) => {
|
||||
if (tx.isCancellationTx) {
|
||||
|
@ -120,7 +121,7 @@ const createTransaction = ({
|
|||
|
||||
let txHash
|
||||
let tx
|
||||
const txArgs = {
|
||||
const txArgs: TxArgs = {
|
||||
safeInstance,
|
||||
to,
|
||||
valueInWei,
|
||||
|
@ -129,7 +130,7 @@ const createTransaction = ({
|
|||
nonce,
|
||||
safeTxGas,
|
||||
baseGas: 0,
|
||||
gasPrice: 0,
|
||||
gasPrice: '0',
|
||||
gasToken: ZERO_ADDRESS,
|
||||
refundReceiver: ZERO_ADDRESS,
|
||||
sender: from,
|
||||
|
@ -164,7 +165,7 @@ const createTransaction = ({
|
|||
sendParams.gas = '7000000'
|
||||
}
|
||||
|
||||
const txToMock = {
|
||||
const txToMock: TxToMock = {
|
||||
...txArgs,
|
||||
confirmations: [], // this is used to determine if a tx is pending or not. See `calculateTransactionStatus` helper
|
||||
value: txArgs.valueInWei,
|
||||
|
@ -223,9 +224,9 @@ const createTransaction = ({
|
|||
.set('executor', from)
|
||||
.set('isExecuted', true)
|
||||
.set('isSuccessful', receipt.status)
|
||||
.set('status', receipt.status ? 'success' : 'failed')
|
||||
.set('status', receipt.status ? TransactionStatus.SUCCESS : TransactionStatus.FAILED)
|
||||
})
|
||||
: mockedTx.set('status', 'awaiting_confirmations')
|
||||
: mockedTx.set('status', TransactionStatus.AWAITING_CONFIRMATIONS)
|
||||
|
||||
await storeTx(
|
||||
toStoreTx.withMutations((record) => {
|
||||
|
|
|
@ -13,12 +13,14 @@ import fetchTransactions from 'src/routes/safe/store/actions/transactions/fetchT
|
|||
import {
|
||||
isCancelTransaction,
|
||||
mockTransaction,
|
||||
TxToMock,
|
||||
} from 'src/routes/safe/store/actions/transactions/utils/transactionHelpers'
|
||||
import { getLastTx, getNewTxNonce, shouldExecuteTransaction } from 'src/routes/safe/store/actions/utils'
|
||||
|
||||
import { getErrorMessage } from 'src/test/utils/ethereumErrors'
|
||||
import { makeConfirmation } from '../models/confirmation'
|
||||
import { storeTx } from './createTransaction'
|
||||
import { TransactionStatus } from '../models/types/transaction'
|
||||
|
||||
const processTransaction = ({
|
||||
approveAndExecute,
|
||||
|
@ -101,7 +103,7 @@ const processTransaction = ({
|
|||
sendParams.gas = '7000000'
|
||||
}
|
||||
|
||||
const txToMock = {
|
||||
const txToMock: TxToMock = {
|
||||
...txArgs,
|
||||
confirmations: [], // this is used to determine if a tx is pending or not. See `calculateTransactionStatus` helper
|
||||
value: txArgs.valueInWei,
|
||||
|
@ -165,11 +167,15 @@ const processTransaction = ({
|
|||
.set('isSuccessful', receipt.status)
|
||||
.set(
|
||||
'status',
|
||||
receipt.status ? (isCancelTransaction(record, safeAddress) ? 'cancelled' : 'success') : 'failed',
|
||||
receipt.status
|
||||
? isCancelTransaction(record, safeAddress)
|
||||
? TransactionStatus.CANCELLED
|
||||
: TransactionStatus.SUCCESS
|
||||
: TransactionStatus.FAILED,
|
||||
)
|
||||
.updateIn(['ownersWithPendingActions', 'reject'], (prev) => prev.clear())
|
||||
})
|
||||
: mockedTx.set('status', 'awaiting_confirmations')
|
||||
: mockedTx.set('status', TransactionStatus.AWAITING_CONFIRMATIONS)
|
||||
|
||||
await storeTx(
|
||||
toStoreTx.withMutations((record) => {
|
||||
|
|
|
@ -7,14 +7,18 @@ import { PROVIDER_REDUCER_ID } from 'src/logic/wallets/store/reducer/provider'
|
|||
import { buildTx, isCancelTransaction } from 'src/routes/safe/store/actions/transactions/utils/transactionHelpers'
|
||||
import { SAFE_REDUCER_ID } from 'src/routes/safe/store/reducer/safe'
|
||||
import { store } from 'src/store'
|
||||
import { DecodedMethods } from 'src/logic/contracts/methodIds'
|
||||
import { DataDecoded } from 'src/logic/contracts/methodIds'
|
||||
import fetchTransactions from 'src/routes/safe/store/actions/transactions/fetchTransactions/fetchTransactions'
|
||||
import { TransactionTypes } from 'src/routes/safe/store/models/types/transaction'
|
||||
import { Transaction, TransactionTypes } from 'src/routes/safe/store/models/types/transaction'
|
||||
import { Token } from 'src/logic/tokens/store/model/token'
|
||||
import { SafeRecord } from 'src/routes/safe/store/models/safe'
|
||||
|
||||
export type ConfirmationServiceModel = {
|
||||
confirmationType: string
|
||||
owner: string
|
||||
submissionDate: Date
|
||||
submissionDate: string
|
||||
signature: string
|
||||
signatureType: string
|
||||
transactionHash: string
|
||||
}
|
||||
|
||||
|
@ -22,25 +26,32 @@ export type TxServiceModel = {
|
|||
baseGas: number
|
||||
blockNumber?: number | null
|
||||
confirmations: ConfirmationServiceModel[]
|
||||
confirmationsRequired: number
|
||||
creationTx?: boolean | null
|
||||
data?: string | null
|
||||
dataDecoded?: DecodedMethods
|
||||
dataDecoded?: DataDecoded
|
||||
ethGasPrice: string
|
||||
executionDate?: string | null
|
||||
executor: string
|
||||
gasPrice: number
|
||||
fee: string
|
||||
gasPrice: string
|
||||
gasToken: string
|
||||
gasUsed: number
|
||||
isExecuted: boolean
|
||||
isSuccessful: boolean
|
||||
modified: string
|
||||
nonce?: number | null
|
||||
operation: number
|
||||
origin?: string | null
|
||||
refundReceiver: string
|
||||
safe: string
|
||||
safeTxGas: number
|
||||
safeTxHash: string
|
||||
signatures: string
|
||||
submissionDate?: string | null
|
||||
to: string
|
||||
transactionHash?: string | null
|
||||
value: number
|
||||
value: string
|
||||
}
|
||||
|
||||
export type SafeTransactionsType = {
|
||||
|
@ -55,8 +66,8 @@ export type OutgoingTxs = {
|
|||
|
||||
export type BatchProcessTxsProps = OutgoingTxs & {
|
||||
currentUser?: string
|
||||
knownTokens: any
|
||||
safe: any
|
||||
knownTokens: Record<string, Token>
|
||||
safe: SafeRecord
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -127,8 +138,8 @@ const batchProcessOutgoingTransactions = async ({
|
|||
outgoingTxs,
|
||||
safe,
|
||||
}: BatchProcessTxsProps): Promise<{
|
||||
cancel: any
|
||||
outgoing: any
|
||||
cancel: Record<string, Transaction>
|
||||
outgoing: Array<Transaction>
|
||||
}> => {
|
||||
// cancellation transactions
|
||||
const cancelTxsValues = Object.values(cancellationTxs)
|
||||
|
|
|
@ -26,18 +26,32 @@ import { TRANSACTIONS_REDUCER_ID } from 'src/routes/safe/store/reducer/transacti
|
|||
import { store } from 'src/store'
|
||||
import { safeSelector, safeTransactionsSelector } from 'src/routes/safe/store/selectors'
|
||||
import { addOrUpdateTransactions } from 'src/routes/safe/store/actions/transactions/addOrUpdateTransactions'
|
||||
import { TxServiceModel } from 'src/routes/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions'
|
||||
import {
|
||||
BatchProcessTxsProps,
|
||||
TxServiceModel,
|
||||
} from 'src/routes/safe/store/actions/transactions/fetchTransactions/loadOutgoingTransactions'
|
||||
import { TypedDataUtils } from 'eth-sig-util'
|
||||
import { Token } from 'src/logic/tokens/store/model/token'
|
||||
import { ProviderRecord } from 'src/logic/wallets/store/model/provider'
|
||||
import { SafeRecord } from 'src/routes/safe/store/models/safe'
|
||||
|
||||
export const isEmptyData = (data?: string | null): boolean => {
|
||||
return !data || data === EMPTY_DATA
|
||||
}
|
||||
|
||||
export const isInnerTransaction = (tx: TxServiceModel, safeAddress: string): boolean => {
|
||||
return sameAddress(tx.to, safeAddress) && Number(tx.value) === 0
|
||||
export const isInnerTransaction = (tx: TxServiceModel | Transaction, safeAddress: string): boolean => {
|
||||
let isSameAddress = false
|
||||
|
||||
if ((tx as TxServiceModel).to !== undefined) {
|
||||
isSameAddress = sameAddress((tx as TxServiceModel).to, safeAddress)
|
||||
} else if ((tx as Transaction).recipient !== undefined) {
|
||||
isSameAddress = sameAddress((tx as Transaction).recipient, safeAddress)
|
||||
}
|
||||
|
||||
return isSameAddress && Number(tx.value) === 0
|
||||
}
|
||||
|
||||
export const isCancelTransaction = (tx: TxServiceModel, safeAddress: string): boolean => {
|
||||
export const isCancelTransaction = (tx: TxServiceModel | Transaction, safeAddress: string): boolean => {
|
||||
return isInnerTransaction(tx, safeAddress) && isEmptyData(tx.data)
|
||||
}
|
||||
|
||||
|
@ -70,7 +84,7 @@ export const isCustomTransaction = async (
|
|||
tx: TxServiceModel,
|
||||
txCode: string,
|
||||
safeAddress: string,
|
||||
knownTokens: any,
|
||||
knownTokens: Record<string, Token>,
|
||||
): Promise<boolean> => {
|
||||
return (
|
||||
isOutgoingTransaction(tx, safeAddress) &&
|
||||
|
@ -81,12 +95,13 @@ export const isCustomTransaction = async (
|
|||
}
|
||||
|
||||
export const getRefundParams = async (
|
||||
tx: any,
|
||||
tx: TxServiceModel,
|
||||
tokenInfo: (string) => Promise<{ decimals: number; symbol: string } | null>,
|
||||
): Promise<any> => {
|
||||
const txGasPrice = Number(tx.gasPrice)
|
||||
let refundParams = null
|
||||
|
||||
if (tx.gasPrice > 0) {
|
||||
if (txGasPrice > 0) {
|
||||
let refundSymbol = 'ETH'
|
||||
let refundDecimals = 18
|
||||
|
||||
|
@ -99,7 +114,9 @@ export const getRefundParams = async (
|
|||
}
|
||||
}
|
||||
|
||||
const feeString = (tx.gasPrice * (tx.baseGas + tx.safeTxGas)).toString().padStart(refundDecimals, '0')
|
||||
const feeString = (txGasPrice * (Number(tx.baseGas) + Number(tx.safeTxGas)))
|
||||
.toString()
|
||||
.padStart(refundDecimals, '0')
|
||||
const whole = feeString.slice(0, feeString.length - refundDecimals) || '0'
|
||||
const fraction = feeString.slice(feeString.length - refundDecimals)
|
||||
|
||||
|
@ -114,18 +131,15 @@ export const getRefundParams = async (
|
|||
|
||||
export const getDecodedParams = (tx: TxServiceModel): DecodedMethods => {
|
||||
if (tx.dataDecoded) {
|
||||
return Object.keys(tx.dataDecoded).reduce((acc, key) => {
|
||||
acc[key] = {
|
||||
...tx.dataDecoded[key].reduce(
|
||||
(acc, param) => ({
|
||||
...acc,
|
||||
[param.name]: param.value,
|
||||
}),
|
||||
{},
|
||||
),
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
return {
|
||||
[tx.dataDecoded.method]: tx.dataDecoded.parameters.reduce(
|
||||
(acc, param) => ({
|
||||
...acc,
|
||||
[param.name]: param.value,
|
||||
}),
|
||||
{},
|
||||
),
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
@ -159,7 +173,7 @@ export const isTransactionCancelled = (
|
|||
|
||||
export const calculateTransactionStatus = (
|
||||
tx: Transaction,
|
||||
{ owners, threshold }: any,
|
||||
{ owners, threshold }: SafeRecord,
|
||||
currentUser?: string | null,
|
||||
): TransactionStatusValues => {
|
||||
let txStatus
|
||||
|
@ -212,6 +226,11 @@ export const calculateTransactionType = (tx: Transaction): TransactionTypeValues
|
|||
return txType
|
||||
}
|
||||
|
||||
export type BuildTx = BatchProcessTxsProps & {
|
||||
tx: TxServiceModel
|
||||
txCode: string | null
|
||||
}
|
||||
|
||||
export const buildTx = async ({
|
||||
cancellationTxs,
|
||||
currentUser,
|
||||
|
@ -220,7 +239,7 @@ export const buildTx = async ({
|
|||
safe,
|
||||
tx,
|
||||
txCode,
|
||||
}): Promise<Transaction> => {
|
||||
}: BuildTx): Promise<Transaction> => {
|
||||
const safeAddress = safe.address
|
||||
const isModifySettingsTx = isModifySettingsTransaction(tx, safeAddress)
|
||||
const isTxCancelled = isTransactionCancelled(tx, outgoingTxs, cancellationTxs)
|
||||
|
@ -235,7 +254,7 @@ export const buildTx = async ({
|
|||
const confirmations = getConfirmations(tx)
|
||||
const { decimals = 18, symbol = 'ETH' } = isSendERC20Tx ? await getERC20DecimalsAndSymbol(tx.to) : {}
|
||||
|
||||
const txToStore: Transaction = makeTransaction({
|
||||
const txToStore = makeTransaction({
|
||||
baseGas: tx.baseGas,
|
||||
blockNumber: tx.blockNumber,
|
||||
cancelled: isTxCancelled,
|
||||
|
@ -276,7 +295,13 @@ export const buildTx = async ({
|
|||
.set('type', calculateTransactionType(txToStore))
|
||||
}
|
||||
|
||||
export const mockTransaction = (tx, safeAddress: string, state): Promise<any> => {
|
||||
export type TxToMock = TxArgs & {
|
||||
confirmations: []
|
||||
safeTxHash: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export const mockTransaction = (tx: TxToMock, safeAddress: string, state): Promise<Transaction> => {
|
||||
const submissionDate = new Date().toISOString()
|
||||
|
||||
const transactionStructure: TxServiceModel = {
|
||||
|
@ -301,8 +326,8 @@ export const mockTransaction = (tx, safeAddress: string, state): Promise<any> =>
|
|||
...tx,
|
||||
}
|
||||
|
||||
const knownTokens = state[TOKEN_REDUCER_ID]
|
||||
const safe = state[SAFE_REDUCER_ID].getIn([SAFE_REDUCER_ID, safeAddress])
|
||||
const knownTokens: Record<string, Token> = state[TOKEN_REDUCER_ID]
|
||||
const safe: SafeRecord = state[SAFE_REDUCER_ID].getIn([SAFE_REDUCER_ID, safeAddress])
|
||||
const cancellationTxs = state[CANCELLATION_TRANSACTIONS_REDUCER_ID].get(safeAddress) || Map()
|
||||
const outgoingTxs = state[TRANSACTIONS_REDUCER_ID].get(safeAddress) || List()
|
||||
|
||||
|
@ -317,7 +342,7 @@ export const mockTransaction = (tx, safeAddress: string, state): Promise<any> =>
|
|||
})
|
||||
}
|
||||
|
||||
export const updateStoredTransactionsStatus = (dispatch, walletRecord): void => {
|
||||
export const updateStoredTransactionsStatus = (dispatch: (any) => void, walletRecord: ProviderRecord): void => {
|
||||
const state = store.getState()
|
||||
const safe = safeSelector(state)
|
||||
|
||||
|
@ -351,7 +376,8 @@ export function generateSafeTxHash(safeAddress: string, txArgs: TxArgs): string
|
|||
{ type: 'uint256', name: 'nonce' },
|
||||
],
|
||||
}
|
||||
const primaryType = 'SafeTx' as const
|
||||
|
||||
const primaryType: 'SafeTx' = 'SafeTx' as const
|
||||
|
||||
const typedData = {
|
||||
types: messageTypes,
|
||||
|
|
|
@ -1,6 +1,25 @@
|
|||
import { List, Map, Record, Set } from 'immutable'
|
||||
import { List, Map, Record, RecordOf, Set } from 'immutable'
|
||||
|
||||
const SafeRecord = Record({
|
||||
export type SafeRecordProps = {
|
||||
name: string
|
||||
address: string
|
||||
threshold: number
|
||||
ethBalance: number
|
||||
owners: List<{ name: string; address: string }>
|
||||
activeTokens: Set<string>
|
||||
activeAssets: Set<string>
|
||||
blacklistedTokens: Set<string>
|
||||
blacklistedAssets: Set<string>
|
||||
balances: Map<string, string>
|
||||
nonce: number
|
||||
latestIncomingTxBlock: number
|
||||
recurringUser?: boolean
|
||||
currentVersion: string
|
||||
needsUpdate: boolean
|
||||
featuresEnabled: Array<string>
|
||||
}
|
||||
|
||||
const makeSafe = Record<SafeRecordProps>({
|
||||
name: '',
|
||||
address: '',
|
||||
threshold: 0,
|
||||
|
@ -19,4 +38,6 @@ const SafeRecord = Record({
|
|||
featuresEnabled: [],
|
||||
})
|
||||
|
||||
export default SafeRecord
|
||||
export type SafeRecord = RecordOf<SafeRecordProps>
|
||||
|
||||
export default makeSafe
|
||||
|
|
|
@ -2,8 +2,8 @@ import { List, Map, Record } from 'immutable'
|
|||
|
||||
import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses'
|
||||
import {
|
||||
TransactionProps,
|
||||
PendingActionType,
|
||||
TransactionProps,
|
||||
TransactionStatus,
|
||||
TransactionTypes,
|
||||
} from 'src/routes/safe/store/models/types/transaction'
|
||||
|
@ -24,7 +24,7 @@ export const makeTransaction = Record<TransactionProps>({
|
|||
executionTxHash: undefined,
|
||||
executor: '',
|
||||
factoryAddress: '',
|
||||
gasPrice: 0,
|
||||
gasPrice: '0',
|
||||
gasToken: ZERO_ADDRESS,
|
||||
isCancellationTx: false,
|
||||
isCollectibleTransfer: false,
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
import { List, Map, RecordOf } from 'immutable'
|
||||
import { DecodedMethods } from 'src/logic/contracts/methodIds'
|
||||
import { Confirmation } from './confirmation'
|
||||
|
||||
export enum TransactionTypes {
|
||||
INCOMING = 'incoming',
|
||||
OUTGOING = 'outgoing',
|
||||
|
@ -32,19 +36,19 @@ export type TransactionProps = {
|
|||
baseGas: number
|
||||
blockNumber?: number | null
|
||||
cancelled?: boolean
|
||||
confirmations: import('immutable').List<any>
|
||||
confirmations: List<Confirmation>
|
||||
created: boolean
|
||||
creator: string
|
||||
creationTx: boolean
|
||||
customTx: boolean
|
||||
data?: string | null
|
||||
decimals?: (number | string) | null
|
||||
decodedParams: import('src/logic/contracts/methodIds').DecodedMethods
|
||||
decodedParams: DecodedMethods
|
||||
executionDate?: string | null
|
||||
executionTxHash?: string | null
|
||||
executor: string
|
||||
factoryAddress: string
|
||||
gasPrice: number
|
||||
gasPrice: string
|
||||
gasToken: string
|
||||
isCancellationTx: boolean
|
||||
isCollectibleTransfer: boolean
|
||||
|
@ -58,7 +62,7 @@ export type TransactionProps = {
|
|||
nonce?: number | null
|
||||
operation: number
|
||||
origin: string | null
|
||||
ownersWithPendingActions: import('immutable').Map<PendingActionValues, import('immutable').List<any>>
|
||||
ownersWithPendingActions: Map<PendingActionValues, List<any>>
|
||||
recipient: string
|
||||
refundParams: any
|
||||
refundReceiver: string
|
||||
|
@ -68,26 +72,26 @@ export type TransactionProps = {
|
|||
status?: TransactionStatus
|
||||
submissionDate?: string | null
|
||||
symbol?: string | null
|
||||
transactionHash: string
|
||||
transactionHash: string | null
|
||||
type: TransactionTypes
|
||||
upgradeTx: boolean
|
||||
value: string
|
||||
}
|
||||
|
||||
export type Transaction = import('immutable').RecordOf<TransactionProps>
|
||||
export type Transaction = RecordOf<TransactionProps>
|
||||
|
||||
export type TxArgs = {
|
||||
data: any
|
||||
baseGas: number
|
||||
data?: string | null
|
||||
gasPrice: string
|
||||
gasToken: string
|
||||
safeInstance: any
|
||||
nonce: number
|
||||
valueInWei: any
|
||||
safeTxGas: number
|
||||
operation: number
|
||||
refundReceiver: string
|
||||
sender: any
|
||||
safeInstance: any
|
||||
safeTxGas: number
|
||||
sender?: string
|
||||
sigs: string
|
||||
to: any
|
||||
operation: any
|
||||
gasPrice: number
|
||||
to: string
|
||||
valueInWei: string
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import { SET_DEFAULT_SAFE } from 'src/routes/safe/store/actions/setDefaultSafe'
|
|||
import { SET_LATEST_MASTER_CONTRACT_VERSION } from 'src/routes/safe/store/actions/setLatestMasterContractVersion'
|
||||
import { UPDATE_SAFE } from 'src/routes/safe/store/actions/updateSafe'
|
||||
import { makeOwner } from 'src/routes/safe/store/models/owner'
|
||||
import SafeRecord from 'src/routes/safe/store/models/safe'
|
||||
import makeSafe from 'src/routes/safe/store/models/safe'
|
||||
import { checksumAddress } from 'src/utils/checksumAddress'
|
||||
|
||||
export const SAFE_REDUCER_ID = 'safes'
|
||||
|
@ -74,7 +74,7 @@ export default handleActions(
|
|||
return state.updateIn([SAFE_REDUCER_ID, safe.address], (prevSafe) => prevSafe.merge(safe))
|
||||
}
|
||||
|
||||
return state.setIn([SAFE_REDUCER_ID, safe.address], SafeRecord(safe))
|
||||
return state.setIn([SAFE_REDUCER_ID, safe.address], makeSafe(safe))
|
||||
},
|
||||
[REMOVE_SAFE]: (state, action) => {
|
||||
const safeAddress = action.payload
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//
|
||||
/* eslint-disable max-classes-per-file */
|
||||
import SafeRecord, { } from 'src/routes/safe/store/models/safe'
|
||||
import addSafe, { buildOwnersFrom } from 'src/routes/safe/store/actions/addSafe'
|
||||
import makeSafe from 'src/routes/safe/store/models/safe'
|
||||
import { buildOwnersFrom } from 'src/routes/safe/store/actions/addSafe'
|
||||
import {
|
||||
FIELD_NAME,
|
||||
FIELD_CONFIRMATIONS,
|
||||
|
@ -11,7 +9,6 @@ import {
|
|||
} from 'src/routes/open/components/fields'
|
||||
import { getWeb3, getProviderInfo } from 'src/logic/wallets/getWeb3'
|
||||
import { createSafe, } from 'src/routes/open/container/Open'
|
||||
import { } from 'src/store/index'
|
||||
import { makeProvider } from 'src/logic/wallets/store/model/provider'
|
||||
import addProvider from 'src/logic/wallets/store/actions/addProvider'
|
||||
|
||||
|
@ -19,7 +16,7 @@ class SafeBuilder {
|
|||
safe
|
||||
|
||||
constructor() {
|
||||
this.safe = SafeRecord()
|
||||
this.safe = makeSafe()
|
||||
}
|
||||
|
||||
withAddress(address) {
|
||||
|
@ -90,7 +87,7 @@ export const aMinedSafe = async (
|
|||
form[getOwnerNameBy(i)] = `Adol ${i + 1} Eth Account`
|
||||
form[getOwnerAddressBy(i)] = accounts[i]
|
||||
}
|
||||
|
||||
|
||||
const openSafeProps = await createSafe(form, accounts[0])
|
||||
|
||||
return openSafeProps.safeAddress
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
//
|
||||
import { } from 'react-router-dom'
|
||||
import { buildMatchPropsFrom } from 'src/test/utils/buildReactRouterProps'
|
||||
import { safeSelector } from 'src/routes/safe/store/selectors/index'
|
||||
|
|
Loading…
Reference in New Issue