From 6a5eb5c2561cf004617302c63068b324429212a0 Mon Sep 17 00:00:00 2001 From: Michael <30682308+mike10ca@users.noreply.github.com> Date: Fri, 11 Oct 2024 14:36:42 +0200 Subject: [PATCH] Tests: Cleanup prod tests (#4362) --- cypress/e2e/pages/create_tx.pages.js | 6 +++++- cypress/e2e/pages/safeapps.pages.js | 4 +++- cypress/e2e/prodhealthcheck/add_owner.cy.js | 5 +---- cypress/e2e/prodhealthcheck/create_tx.cy.js | 4 +--- cypress/e2e/prodhealthcheck/load_safe.cy.js | 13 ------------- cypress/e2e/prodhealthcheck/messages_onchain.cy.js | 2 -- cypress/e2e/prodhealthcheck/remove_owner.cy.js | 3 +-- cypress/e2e/prodhealthcheck/sidebar.cy.js | 4 ---- cypress/e2e/prodhealthcheck/spending_limits.cy.js | 8 -------- cypress/e2e/prodhealthcheck/swaps_history_2.cy.js | 2 -- cypress/e2e/prodhealthcheck/swaps_tokens.cy.js | 2 -- cypress/e2e/prodhealthcheck/tokens.cy.js | 6 ------ cypress/e2e/prodhealthcheck/tx_history.cy.js | 7 ------- cypress/e2e/regression/swaps_history_2.cy.js | 12 ++++++++++++ cypress/e2e/safe-apps/tx-builder.spec.cy.js | 8 ++++++++ cypress/fixtures/swaps_data.json | 4 +++- 16 files changed, 34 insertions(+), 56 deletions(-) diff --git a/cypress/e2e/pages/create_tx.pages.js b/cypress/e2e/pages/create_tx.pages.js index 37361e213c..5daa1ba448 100644 --- a/cypress/e2e/pages/create_tx.pages.js +++ b/cypress/e2e/pages/create_tx.pages.js @@ -263,6 +263,10 @@ export function verifyExpandedDetails(data, warning) { if (warning) cy.get(warning).should('be.visible') } +export function verifyAdvancedDetails(data) { + main.checkTextsExistWithinElement(accordionDetails, data) +} + export function verifyActions(data) { main.checkTextsExistWithinElement(accordionDetails, data) } @@ -273,7 +277,7 @@ export function clickOnExpandableAction(data) { }) } -function clickOnAdvancedDetails() { +export function clickOnAdvancedDetails() { cy.get(advancedDetails).click() } diff --git a/cypress/e2e/pages/safeapps.pages.js b/cypress/e2e/pages/safeapps.pages.js index a673a864c4..b4fc900f93 100644 --- a/cypress/e2e/pages/safeapps.pages.js +++ b/cypress/e2e/pages/safeapps.pages.js @@ -52,6 +52,7 @@ export const selectAllRowsChbxStr = /Select All Rows checkbox/i export const selectRowChbxStr = /Select Row checkbox/i export const recipientStr = /recipient/i export const validRecipientAddressStr = /please enter a valid recipient address/i +export const contractMethodSelector = 'input[id="contract-method-selector"]' export const testAddressValue2 = 'testAddressValue' export const testBooleanValue = 'testBooleanValue' export const testFallback = 'fallback' @@ -103,6 +104,7 @@ export const transactiobUilderHeadlinePreview = 'Transaction Builder' export const availableNetworksPreview = 'Available networks' export const connecttextPreview = 'Compose custom contract interactions and batch them into a single transaction' const warningDefaultAppStr = 'The application you are trying to access is not in the default Safe Apps list' +export const AddressEmptyCodeStr = 'AddressEmptyCode' export const localStorageItem = '{"https://safe-test-app.com":[{"feature":"camera","status":"granted"},{"feature":"microphone","status":"denied"}]}' export const gridItem = 'main .MuiPaper-root > .MuiGrid-item' @@ -111,7 +113,7 @@ export const linkNames = { txBuilderLogo: /Transaction Builder logo/i, } export const abi = - '[{{}"inputs":[{{}"internalType":"address","name":"_singleton","type":"address"{}}],"stateMutability":"nonpayable","type":"constructor"{}},{{}"stateMutability":"payable","type":"fallback"{}}]' + '[{"inputs":[{"internalType":"address","name":"_singleton","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]' export const permissionCheckboxes = { camera: 'input[name="camera"]', diff --git a/cypress/e2e/prodhealthcheck/add_owner.cy.js b/cypress/e2e/prodhealthcheck/add_owner.cy.js index 539ecc8ce6..714c942234 100644 --- a/cypress/e2e/prodhealthcheck/add_owner.cy.js +++ b/cypress/e2e/prodhealthcheck/add_owner.cy.js @@ -1,5 +1,4 @@ import * as constants from '../../support/constants' -import * as main from '../../e2e/pages/main.page' import * as owner from '../pages/owners.pages' import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js' import * as wallet from '../../support/utils/wallet.js' @@ -18,13 +17,11 @@ describe('[PROD] Add Owners tests', () => { cy.contains(owner.safeAccountNonceStr, { timeout: 10000 }) }) - // TODO: Added to prod it('Verify add owner button is disabled for disconnected user', () => { owner.verifyAddOwnerBtnIsDisabled() }) - // TODO: Added to prod - it.skip('Verify the Add New Owner Form can be opened', () => { + it('Verify the Add New Owner Form can be opened', () => { wallet.connectSigner(signer) owner.openAddOwnerWindow() }) diff --git a/cypress/e2e/prodhealthcheck/create_tx.cy.js b/cypress/e2e/prodhealthcheck/create_tx.cy.js index 9f3df5161b..b2fc30bf1a 100644 --- a/cypress/e2e/prodhealthcheck/create_tx.cy.js +++ b/cypress/e2e/prodhealthcheck/create_tx.cy.js @@ -1,5 +1,4 @@ import * as constants from '../../support/constants' -import * as main from '../../e2e/pages/main.page' import * as createtx from '../../e2e/pages/create_tx.pages' import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js' import * as wallet from '../../support/utils/wallet.js' @@ -18,7 +17,7 @@ function happyPathToStepTwo() { createtx.clickOnNextBtn() } -describe.skip('[PROD] Create transactions tests', () => { +describe('[PROD] Create transactions tests', () => { before(async () => { staticSafes = await getSafes(CATEGORIES.static) }) @@ -30,7 +29,6 @@ describe.skip('[PROD] Create transactions tests', () => { createtx.clickOnSendTokensBtn() }) - // TODO: Added to prod it('Verify submitting a tx and that clicking on notification shows the transaction in queue', () => { happyPathToStepTwo() createtx.verifySubmitBtnIsEnabled() diff --git a/cypress/e2e/prodhealthcheck/load_safe.cy.js b/cypress/e2e/prodhealthcheck/load_safe.cy.js index 8d1e630c36..760ffbc945 100644 --- a/cypress/e2e/prodhealthcheck/load_safe.cy.js +++ b/cypress/e2e/prodhealthcheck/load_safe.cy.js @@ -1,6 +1,5 @@ import 'cypress-file-upload' import * as constants from '../../support/constants' -import * as main from '../pages/main.page' import * as safe from '../pages/load_safe.pages' import * as createwallet from '../pages/create_wallet.pages' import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js' @@ -9,17 +8,6 @@ let staticSafes = [] const testSafeName = 'Test safe name' const testOwnerName = 'Test Owner Name' -// TODO -const SAFE_ENS_NAME = 'test20.eth' -const SAFE_ENS_NAME_TRANSLATED = constants.EOA - -const EOA_ADDRESS = constants.EOA - -const INVALID_ADDRESS_ERROR_MSG = 'Address given is not a valid Safe address' - -// TODO -const OWNER_ENS_DEFAULT_NAME = 'test20.eth' -const OWNER_ADDRESS = constants.EOA describe('[PROD] Load Safe tests', () => { before(async () => { @@ -31,7 +19,6 @@ describe('[PROD] Load Safe tests', () => { cy.wait(2000) }) - // TODO: Added to prod it('Verify Safe and owner names are displayed in the Review step', () => { safe.inputNameAndAddress(testSafeName, staticSafes.SEP_STATIC_SAFE_4) safe.clickOnNextBtn() diff --git a/cypress/e2e/prodhealthcheck/messages_onchain.cy.js b/cypress/e2e/prodhealthcheck/messages_onchain.cy.js index 5b4f0928cd..74c9df12a8 100644 --- a/cypress/e2e/prodhealthcheck/messages_onchain.cy.js +++ b/cypress/e2e/prodhealthcheck/messages_onchain.cy.js @@ -1,5 +1,4 @@ import * as constants from '../../support/constants.js' -import * as main from '../pages/main.page.js' import * as createTx from '../pages/create_tx.pages.js' import * as msg_data from '../../fixtures/txmessages_data.json' import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js' @@ -17,7 +16,6 @@ describe('[PROD] Onchain Messages tests', () => { cy.visit(constants.prodbaseUrl + constants.transactionsHistoryUrl + staticSafes.SEP_STATIC_SAFE_10) }) - // TODO: Added to prod it('Verify summary for signed on-chain message', () => { createTx.verifySummaryByName( typeMessagesOnchain.contractName, diff --git a/cypress/e2e/prodhealthcheck/remove_owner.cy.js b/cypress/e2e/prodhealthcheck/remove_owner.cy.js index 755f320db1..734bcf0a60 100644 --- a/cypress/e2e/prodhealthcheck/remove_owner.cy.js +++ b/cypress/e2e/prodhealthcheck/remove_owner.cy.js @@ -21,8 +21,7 @@ describe('[PROD] Remove Owners tests', () => { cy.contains(owner.safeAccountNonceStr, { timeout: 10000 }) }) - // TODO: Added to prod - it.skip('Verify owner deletion transaction has been created', () => { + it('Verify owner deletion transaction has been created', () => { wallet.connectSigner(signer) owner.waitForConnectionStatus() owner.openRemoveOwnerWindow(1) diff --git a/cypress/e2e/prodhealthcheck/sidebar.cy.js b/cypress/e2e/prodhealthcheck/sidebar.cy.js index edb534286f..ca2f71dd59 100644 --- a/cypress/e2e/prodhealthcheck/sidebar.cy.js +++ b/cypress/e2e/prodhealthcheck/sidebar.cy.js @@ -18,25 +18,21 @@ describe('[PROD] Sidebar tests', () => { cy.visit(constants.prodbaseUrl + constants.homeUrl + staticSafes.SEP_STATIC_SAFE_9) }) - // TODO: Added to prod it('Verify current safe details', () => { sideBar.verifySafeHeaderDetails(sideBar.testSafeHeaderDetails) }) - // TODO: Added to prod it.skip('Verify New transaction button enabled for owners', () => { wallet.connectSigner(signer) sideBar.verifyNewTxBtnStatus(constants.enabledStates.enabled) }) - // TODO: Added to prod it.skip('Verify New transaction button enabled for beneficiaries who are non-owners', () => { cy.visit(constants.prodbaseUrl + constants.homeUrl + staticSafes.SEP_STATIC_SAFE_11) wallet.connectSigner(signer) sideBar.verifyNewTxBtnStatus(constants.enabledStates.enabled) }) - // TODO: Added to prod it('Verify New Transaction button disabled for non-owners', () => { main.verifyElementsCount(navigation.newTxBtn, 0) }) diff --git a/cypress/e2e/prodhealthcheck/spending_limits.cy.js b/cypress/e2e/prodhealthcheck/spending_limits.cy.js index e1f663f6db..85ada66099 100644 --- a/cypress/e2e/prodhealthcheck/spending_limits.cy.js +++ b/cypress/e2e/prodhealthcheck/spending_limits.cy.js @@ -1,5 +1,4 @@ import * as constants from '../../support/constants' -import * as main from '../pages/main.page' import * as spendinglimit from '../pages/spending_limits.pages' import * as navigation from '../pages/navigation.page' import * as tx from '../pages/create_tx.pages' @@ -9,11 +8,7 @@ import * as wallet from '../../support/utils/wallet.js' let staticSafes = [] const walletCredentials = JSON.parse(Cypress.env('CYPRESS_WALLET_CREDENTIALS')) const signer = walletCredentials.OWNER_4_PRIVATE_KEY -const signerAddress = walletCredentials.OWNER_4_WALLET_ADDRESS - const tokenAmount = 0.1 -const newTokenAmount = 0.001 -const spendingLimitBalance = '(0.15 ETH)' describe('[PROD] Spending limits tests', () => { before(async () => { @@ -25,7 +20,6 @@ describe('[PROD] Spending limits tests', () => { cy.get(spendinglimit.spendingLimitsSection).should('be.visible') }) - // TODO: Added to prod it.skip('Verify that the Review step shows beneficiary, amount allowed, reset time', () => { //Assume that default reset time is set to One time wallet.connectSigner(signer) @@ -40,12 +34,10 @@ describe('[PROD] Spending limits tests', () => { ) }) - // TODO: Added to prod it('Verify values and trash icons are displayed in Beneficiary table', () => { spendinglimit.verifyBeneficiaryTable() }) - // TODO: Added to prod it.skip('Verify Spending limit option is available when selecting the corresponding token', () => { wallet.connectSigner(signer) navigation.clickOnNewTxBtn() diff --git a/cypress/e2e/prodhealthcheck/swaps_history_2.cy.js b/cypress/e2e/prodhealthcheck/swaps_history_2.cy.js index 96f76e9f42..c7754c0600 100644 --- a/cypress/e2e/prodhealthcheck/swaps_history_2.cy.js +++ b/cypress/e2e/prodhealthcheck/swaps_history_2.cy.js @@ -14,7 +14,6 @@ describe('[PROD] Swaps history tests 2', () => { staticSafes = await getSafes(CATEGORIES.static) }) - // TODO: Added to prod it('Verify swap buy operation with 2 actions: approve & swap', { defaultCommandTimeout: 30000 }, () => { cy.visit( constants.prodbaseUrl + constants.transactionUrl + staticSafes.SEP_STATIC_SAFE_1 + swaps.swapTxs.buy2actions, @@ -34,7 +33,6 @@ describe('[PROD] Swaps history tests 2', () => { ]) }) - // TODO: Added to prod // TODO: Unskip after next release due to changes in design tx it.skip( 'Verify no decoding if tx was created using CowSwap safe-app in the history', diff --git a/cypress/e2e/prodhealthcheck/swaps_tokens.cy.js b/cypress/e2e/prodhealthcheck/swaps_tokens.cy.js index acc2f9a5fa..b849e92c72 100644 --- a/cypress/e2e/prodhealthcheck/swaps_tokens.cy.js +++ b/cypress/e2e/prodhealthcheck/swaps_tokens.cy.js @@ -20,7 +20,6 @@ describe('[PROD] Swaps token tests', () => { cy.visit(constants.prodbaseUrl + constants.BALANCE_URL + staticSafes.SEP_STATIC_SAFE_1) }) - // TODO: Added to prod it.skip( 'Verify that clicking the swap from assets tab, autofills that token automatically in the form', { defaultCommandTimeout: 30000 }, @@ -37,7 +36,6 @@ describe('[PROD] Swaps token tests', () => { }, ) - // TODO: Added to prod // TODO: Check why expected number of buttons not displayed sometimes it.skip('Verify swap button are displayed in assets table and dashboard', () => { assets.selectTokenList(assets.tokenListOptions.allTokens) diff --git a/cypress/e2e/prodhealthcheck/tokens.cy.js b/cypress/e2e/prodhealthcheck/tokens.cy.js index 14b18ab68d..9be1b428c6 100644 --- a/cypress/e2e/prodhealthcheck/tokens.cy.js +++ b/cypress/e2e/prodhealthcheck/tokens.cy.js @@ -1,9 +1,7 @@ import * as constants from '../../support/constants' -import * as main from '../pages/main.page' import * as assets from '../pages/assets.pages' import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js' -const ASSET_NAME_COLUMN = 0 const TOKEN_AMOUNT_COLUMN = 1 const FIAT_AMOUNT_COLUMN = 2 @@ -19,7 +17,6 @@ describe('[PROD] Prod tokens tests', () => { cy.visit(constants.prodbaseUrl + constants.BALANCE_URL + staticSafes.SEP_STATIC_SAFE_2) }) - // TODO: Added to prod it('Verify that non-native tokens are present and have balance', () => { assets.selectTokenList(assets.tokenListOptions.allTokens) assets.verifyBalance(assets.currencyDaiCap, TOKEN_AMOUNT_COLUMN, assets.currencyDaiAlttext) @@ -77,15 +74,12 @@ describe('[PROD] Prod tokens tests', () => { ) }) - // TODO: Added to prod - //Include in smoke. it('Verify that when owner is disconnected, Send button is disabled', () => { assets.selectTokenList(assets.tokenListOptions.allTokens) assets.showSendBtn(0) assets.VerifySendButtonIsDisabled() }) - // TODO: Added to prod it('Verify that when connected user is not owner, Send button is disabled', () => { cy.visit(constants.prodbaseUrl + constants.BALANCE_URL + staticSafes.SEP_STATIC_SAFE_3) assets.selectTokenList(assets.tokenListOptions.allTokens) diff --git a/cypress/e2e/prodhealthcheck/tx_history.cy.js b/cypress/e2e/prodhealthcheck/tx_history.cy.js index 25bef3d1c3..9186eea8b9 100644 --- a/cypress/e2e/prodhealthcheck/tx_history.cy.js +++ b/cypress/e2e/prodhealthcheck/tx_history.cy.js @@ -35,7 +35,6 @@ describe('[PROD] Tx history tests 1', () => { cy.wait('@allTransactions') }) - // TODO: Added to prod // Account creation it('Verify summary for account creation', () => { createTx.verifySummaryByName( @@ -45,7 +44,6 @@ describe('[PROD] Tx history tests 1', () => { ) }) - // TODO: Added to prod it('Verify exapanded details for account creation', () => { createTx.clickOnTransactionItemByName(typeCreateAccount.title) createTx.verifyExpandedDetails([ @@ -61,7 +59,6 @@ describe('[PROD] Tx history tests 1', () => { ]) }) - // TODO: Added to prod // Token send it('Verify exapanded details for token send', () => { createTx.clickOnTransactionItemByName(typeSend.title, typeSend.summaryTxInfo) @@ -73,7 +70,6 @@ describe('[PROD] Tx history tests 1', () => { ]) }) - // TODO: Added to prod // Spending limits // TODO: Unskip after next release due to design tx it.skip('Verify summary for setting spend limits', () => { @@ -85,7 +81,6 @@ describe('[PROD] Tx history tests 1', () => { ) }) - // TODO: Added to prod // TODO: Unskip after next release due to design tx it.skip('Verify exapanded details for initial spending limits setup', () => { createTx.clickOnTransactionItemByName(typeSpendingLimits.title, typeSpendingLimits.summaryTxInfo) @@ -100,7 +95,6 @@ describe('[PROD] Tx history tests 1', () => { ) }) - // TODO: Added to prod // TODO: Unskip after next release due to design tx it.skip('Verify that 3 actions exist in initial spending limits setup', () => { createTx.clickOnTransactionItemByName(typeSpendingLimits.title, typeSpendingLimits.summaryTxInfo) @@ -125,7 +119,6 @@ describe('[PROD] Tx history tests 1', () => { ]) }) - // TODO: Added to prod it('Verify advanced details displayed in exapanded details for allowance deletion', () => { createTx.clickOnTransactionItemByName(typeDeleteAllowance.title, typeDeleteAllowance.summaryTxInfo) createTx.expandAdvancedDetails([typeDeleteAllowance.baseGas]) diff --git a/cypress/e2e/regression/swaps_history_2.cy.js b/cypress/e2e/regression/swaps_history_2.cy.js index 4239df2120..f01497e9c2 100644 --- a/cypress/e2e/regression/swaps_history_2.cy.js +++ b/cypress/e2e/regression/swaps_history_2.cy.js @@ -22,6 +22,8 @@ describe('Swaps history tests 2', () => { const eq = swaps.createRegex(swapsHistory.DAIeqCOW, 'COW') create_tx.verifyExpandedDetails([swapsHistory.sellFull, dai, eq, swapsHistory.dai, swapsHistory.filled]) + create_tx.clickOnAdvancedDetails() + create_tx.verifyAdvancedDetails([swapsHistory.gGpV2, swapsHistory.actionPreSignatureG]) }) // TODO: Added to prod @@ -42,6 +44,8 @@ describe('Swaps history tests 2', () => { swapsHistory.actionApprove, swapsHistory.actionPreSignature, ]) + create_tx.clickOnAdvancedDetails() + create_tx.verifyAdvancedDetails([swapsHistory.multiSend, swapsHistory.multiSendCallOnly1_3_0]) }) it('Verify "Cancelled" status for manually cancelled limit orders', { defaultCommandTimeout: 30000 }, () => { @@ -60,6 +64,8 @@ describe('Swaps history tests 2', () => { swapsHistory.cow, swapsHistory.cancelled, ]) + create_tx.clickOnAdvancedDetails() + create_tx.verifyAdvancedDetails([swapsHistory.gGpV2, swapsHistory.actionPreSignatureG]) }) it('Verify swap operation with 3 actions: wrap & approve & swap', { defaultCommandTimeout: 30000 }, () => { @@ -79,6 +85,8 @@ describe('Swaps history tests 2', () => { swapsHistory.actionPreSignature, swapsHistory.actionDepositEth, ]) + create_tx.clickOnAdvancedDetails() + create_tx.verifyAdvancedDetails([swapsHistory.multiSend, swapsHistory.multiSendCallOnly1_3_0]) }) it('Verify "Expired" field in the tx details for limit orders', { defaultCommandTimeout: 30000 }, () => { @@ -89,6 +97,8 @@ describe('Swaps history tests 2', () => { const eq = swaps.createRegex(swapsHistory.DAIeqCOW, 'COW') create_tx.verifyExpandedDetails([swapsHistory.sellOrder, swapsHistory.sell, dai, eq, swapsHistory.expired]) + create_tx.clickOnAdvancedDetails() + create_tx.verifyAdvancedDetails([swapsHistory.gGpV2, swapsHistory.actionPreSignatureG]) }) it('Verify "Filled" field in the tx details for limit orders', { defaultCommandTimeout: 30000 }, () => { @@ -99,6 +109,8 @@ describe('Swaps history tests 2', () => { const eq = swaps.createRegex(swapsHistory.USDTeqUSDC, 'USDC') create_tx.verifyExpandedDetails([swapsHistory.sellOrder, swapsHistory.sell, usdc, eq, swapsHistory.filled]) + create_tx.clickOnAdvancedDetails() + create_tx.verifyAdvancedDetails([swapsHistory.gGpV2, swapsHistory.actionPreSignatureG]) }) // TODO: Added to prod diff --git a/cypress/e2e/safe-apps/tx-builder.spec.cy.js b/cypress/e2e/safe-apps/tx-builder.spec.cy.js index 8bf6f67ce6..143e648e79 100644 --- a/cypress/e2e/safe-apps/tx-builder.spec.cy.js +++ b/cypress/e2e/safe-apps/tx-builder.spec.cy.js @@ -225,4 +225,12 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => { }) }) }) + + it('Verify that error types are not displayed in ABI methods', () => { + cy.enter(iframeSelector).then((getBody) => { + getBody().findByLabelText(safeapps.enterABIStr).type(safeapps.abi, { parseSpecialCharSequences: false }) + getBody().find(safeapps.contractMethodSelector).click() + getBody().find(safeapps.AddressEmptyCodeStr).should('not.exist') + }) + }) }) diff --git a/cypress/fixtures/swaps_data.json b/cypress/fixtures/swaps_data.json index 10418befb0..9160f5a338 100644 --- a/cypress/fixtures/swaps_data.json +++ b/cypress/fixtures/swaps_data.json @@ -52,7 +52,9 @@ "partiallyFilled": "Partially filled", "gGpV2": "GPv2Settlement", "safeAppTitile": "CowSwap", - "title": "Swap order" + "title": "Swap order", + "multiSend": "multiSend", + "multiSendCallOnly1_3_0": "Safe: MultiSendCallOnly 1.3.0" } } }