From 4b1a6692e6adbb91a1c8146b5ecf470e2d3928bd Mon Sep 17 00:00:00 2001 From: Lukasz Jagiela Date: Fri, 3 Jan 2025 16:45:08 +0100 Subject: [PATCH] test: e2e - add maintenance scenarios for re-creating test wallets --- .../src/assert/transactionsPageAssert.ts | 14 +++-- .../elements/newTransaction/coinConfigure.ts | 15 +++++- .../newTransaction/tokenSelectionPage.ts | 35 ++++++------ .../elements/onboarding/recoveryPhrasePage.ts | 1 + .../elements/onboarding/walletSetupPage.ts | 12 +++-- .../src/features/WalletMaintenance.feature | 42 +++++++++++++++ .../e2e/StakingInitialFundsE2E.feature | 2 +- .../e2e-tests/src/hooks/beforeTagHooks.ts | 2 +- .../newTransactionExtendedPageObject.ts | 17 +++--- packages/e2e-tests/src/steps/commonSteps.ts | 1 + .../e2e-tests/src/steps/onboardingSteps.ts | 15 ++++-- .../src/steps/sendTransactionSimpleSteps.ts | 13 +++++ .../e2e-tests/src/steps/transactionsSteps.ts | 4 ++ .../src/steps/walletMaintenanceSteps.ts | 53 +++++++++++++++++++ 14 files changed, 188 insertions(+), 38 deletions(-) create mode 100644 packages/e2e-tests/src/features/WalletMaintenance.feature create mode 100644 packages/e2e-tests/src/steps/walletMaintenanceSteps.ts diff --git a/packages/e2e-tests/src/assert/transactionsPageAssert.ts b/packages/e2e-tests/src/assert/transactionsPageAssert.ts index e3e69bfcd4..576e1acd58 100644 --- a/packages/e2e-tests/src/assert/transactionsPageAssert.ts +++ b/packages/e2e-tests/src/assert/transactionsPageAssert.ts @@ -136,9 +136,9 @@ class TransactionsPageAssert { await browser.waitUntil( async () => - ( - await TransactionsPage.transactionsTableItemTokensAmount(rowIndex).getText() - ).includes(expectedTransactionRowAssetDetails.tokensAmount), + (await TransactionsPage.transactionsTableItemTokensAmount(rowIndex).getText()).includes( + expectedTransactionRowAssetDetails.tokensAmount + ), { timeout: 8000, interval: 1000, @@ -194,6 +194,14 @@ class TransactionsPageAssert { expectedColors ); } + + assertCounterShowingMoreTransactionsThan = async (expectedMaxNumber: number) => { + const transactionsCounterValue = Number((await TransactionsPage.counter.getText()).slice(1, -1)); + expect(transactionsCounterValue).to.be.greaterThan( + expectedMaxNumber, + `transactions count is lower than ${expectedMaxNumber}, aborting` + ); + }; } export default new TransactionsPageAssert(); diff --git a/packages/e2e-tests/src/elements/newTransaction/coinConfigure.ts b/packages/e2e-tests/src/elements/newTransaction/coinConfigure.ts index f372de59a1..aa6c0d509c 100644 --- a/packages/e2e-tests/src/elements/newTransaction/coinConfigure.ts +++ b/packages/e2e-tests/src/elements/newTransaction/coinConfigure.ts @@ -1,5 +1,5 @@ /* eslint-disable no-undef */ -import { ChainablePromiseElement } from 'webdriverio'; +import { ChainablePromiseElement, ChainablePromiseArray } from 'webdriverio'; import { setInputFieldValue } from '../../utils/inputFieldUtils'; import { browser } from '@wdio/globals'; @@ -31,6 +31,10 @@ export class CoinConfigure { return $(`${this.CONTAINER}${this.TOKEN_NAME}`); } + get nameElements(): ChainablePromiseArray { + return $$(`${this.CONTAINER}${this.TOKEN_NAME}`); + } + get balanceValueElement(): ChainablePromiseElement { return $(`${this.CONTAINER}${this.TOKEN_VALUE}`); } @@ -111,6 +115,15 @@ export class CoinConfigure { await this.assetMaxButton.click(); }; + getAllTokenNames = async (): Promise => { + const tab = await this.nameElements; + const names: string[] = []; + for (const i of tab) { + names.push(await i.getText()); + } + return names; + }; + clickToLoseFocus = async (): Promise => { await this.drawerNavigationHeader.click(); }; diff --git a/packages/e2e-tests/src/elements/newTransaction/tokenSelectionPage.ts b/packages/e2e-tests/src/elements/newTransaction/tokenSelectionPage.ts index 19fd312cf2..88e19b7108 100644 --- a/packages/e2e-tests/src/elements/newTransaction/tokenSelectionPage.ts +++ b/packages/e2e-tests/src/elements/newTransaction/tokenSelectionPage.ts @@ -3,6 +3,7 @@ import CommonDrawerElements from '../CommonDrawerElements'; import testContext from '../../utils/testContext'; import { generateRandomString } from '../../utils/textUtils'; import { TokenSearchResult } from './tokenSearchResult'; +import { ChainablePromiseElement, ChainablePromiseArray } from 'webdriverio'; class TokenSelectionPage extends CommonDrawerElements { private TOKENS_BUTTON = '//input[@data-testid="asset-selector-button-tokens"]'; @@ -24,23 +25,23 @@ class TokenSelectionPage extends CommonDrawerElements { private SEARCH_INPUT = '[data-testid="asset-selector"] [data-testid="search-input"]'; public NFT_IMAGE = '[data-testid="nft-image"]'; - get tokensButton() { + get tokensButton(): ChainablePromiseElement { return $(this.TOKENS_BUTTON).parentElement().parentElement(); } - get nftsButton() { + get nftsButton(): ChainablePromiseElement { return $(this.NFTS_BUTTON).parentElement().parentElement(); } - get searchInput() { + get searchInput(): ChainablePromiseElement { return $(this.SEARCH_INPUT); } - get nftImages() { + get nftImages(): ChainablePromiseArray { return this.assetSelectorContainer.$$(this.NFT_IMAGE); } - get tokens() { + get tokens(): ChainablePromiseArray { return $$(this.TOKEN_ROW); } @@ -48,19 +49,19 @@ class TokenSelectionPage extends CommonDrawerElements { return new TokenSearchResult(nameOrIndex); } - get assetSelectorContainer() { + get assetSelectorContainer(): ChainablePromiseElement { return $(this.ASSET_SELECTOR_CONTAINER); } - get nftItemSelectedCheckmark() { + get nftItemSelectedCheckmark(): ChainablePromiseElement { return $(this.NFT_ITEM_SELECTED_CHECKMARK); } - get nftContainers() { + get nftContainers(): ChainablePromiseArray { return this.assetSelectorContainer.$$(this.NFT_CONTAINER); } - get nftNames() { + get nftNames(): ChainablePromiseArray { return this.assetSelectorContainer.$$(this.NFT_ITEM_NAME); } @@ -82,35 +83,35 @@ class TokenSelectionPage extends CommonDrawerElements { return this.nftContainers[index].$(this.NFT_ITEM_SELECTED_CHECKMARK); } - get assetsCounter() { + get assetsCounter(): ChainablePromiseElement { return $(this.ASSETS_SELECTION_COUNTER); } - get neutralFaceIcon() { + get neutralFaceIcon(): ChainablePromiseElement { return $(this.NEUTRAL_FACE_ICON); } - get sadFaceIcon() { + get sadFaceIcon(): ChainablePromiseElement { return $(this.SAD_FACE_ICON); } - get emptyStateMessage() { + get emptyStateMessage(): ChainablePromiseElement { return $(this.EMPTY_STATE_MESSAGE); } - get cancelButton() { + get cancelButton(): ChainablePromiseElement { return $(this.CANCEL_BUTTON); } - get clearButton() { + get clearButton(): ChainablePromiseElement { return $(this.CLEAR_BUTTON); } - get selectMultipleButton() { + get selectMultipleButton(): ChainablePromiseElement { return $(this.SELECT_MULTIPLE_BUTTON); } - get addToTransactionButton() { + get addToTransactionButton(): ChainablePromiseElement { return $(this.ADD_TO_TRANSACTION_BUTTON); } diff --git a/packages/e2e-tests/src/elements/onboarding/recoveryPhrasePage.ts b/packages/e2e-tests/src/elements/onboarding/recoveryPhrasePage.ts index efc2584f2d..00057a8eff 100644 --- a/packages/e2e-tests/src/elements/onboarding/recoveryPhrasePage.ts +++ b/packages/e2e-tests/src/elements/onboarding/recoveryPhrasePage.ts @@ -179,6 +179,7 @@ class RecoveryPhrasePage extends CommonOnboardingElements { await ChooseRecoveryMethodPage.nextButton.click(); if (flowType === 'Create') { await this.clickOnCopyToClipboardButton(); + testContext.save('newCreatedWalletMnemonic', await clipboard.read()); await this.nextButton.click(); } if (fillValues) { diff --git a/packages/e2e-tests/src/elements/onboarding/walletSetupPage.ts b/packages/e2e-tests/src/elements/onboarding/walletSetupPage.ts index d796b34516..9ffd55e999 100644 --- a/packages/e2e-tests/src/elements/onboarding/walletSetupPage.ts +++ b/packages/e2e-tests/src/elements/onboarding/walletSetupPage.ts @@ -116,15 +116,19 @@ class WalletSetupPage extends CommonOnboardingElements { async goToWalletSetupPage( flowType: 'Create' | 'Restore', mnemonicWords: string[] = [], - fillValues = false + fillValues = false, + walletName?: string, + walletPassword?: string ): Promise { await recoveryPhrasePage.goToMnemonicVerificationPage(flowType, mnemonicWords, true); await recoveryPhrasePage.nextButton.waitForClickable(); await recoveryPhrasePage.nextButton.click(); if (fillValues) { - await this.setWalletNameInput('TestAutomationWallet'); - await this.setWalletPasswordInput('N_8J@bne87A'); - await this.setWalletPasswordConfirmInput('N_8J@bne87A'); + const name = walletName === undefined ? 'TestAutomationWallet' : walletName.slice(0, 20); + await this.setWalletNameInput(name); + const password = walletPassword === 'default' ? String(process.env.WALLET_1_PASSWORD) : 'N_8J@bne87A'; + await this.setWalletPasswordInput(password); + await this.setWalletPasswordConfirmInput(password); } } } diff --git a/packages/e2e-tests/src/features/WalletMaintenance.feature b/packages/e2e-tests/src/features/WalletMaintenance.feature new file mode 100644 index 0000000000..d0c94f391d --- /dev/null +++ b/packages/e2e-tests/src/features/WalletMaintenance.feature @@ -0,0 +1,42 @@ +@Pending +@WalletMaintenance +Feature: Maintenance feature + + # this feature is for maintenance purposes only + + # scenario below creates new wallet, transfers all funds from desired wallet and + # prints its data that can be later pasted into walletConfiguration file + # replace wallet_name in the Examples sections and let the test finish + # you may still need to manually do the delegation for some wallets + + @RecreateWalletAndTransferAllFunds + Scenario Outline: Extended View - Check if wallet has more than 1000 transactions, if yes then create a new one, transfer all funds and generate wallet repository entry + Given I create new wallet with name: "" and save wallet information + And I click "Receive" button on page header + And I click "Copy" button on "Receive" page for default wallet address + And I open wallet: "" in: extended mode + And I navigate to Transactions extended page + And Transactions counter is showing value higher than 900 + And I navigate to Staking extended page + And I save identifiers of stake pools currently in use + And I click "Send" button on page header + And I fill address input with copied address + And If available: I add all available Token types to bundle 1 + And I click MAX button for all selected tokens + And If available: I add all available NFT types to bundle 1 + And I click "Review transaction" button on "Send" page + And I click "Confirm" button on "Transaction summary" page + When I enter correct password and confirm the transaction + Then The Transaction submitted screen is displayed in extended mode + And I print wallet "" data for walletConfiguration file + Examples: + | wallet_name | + | WalletAnalyticsReceiveSimpleTransaction2E2E | + + @CreateNewWallet + Scenario Outline: Extended View - Create a new wallet and print data + Given I create new wallet with name: "" and save wallet information + And I print wallet "" data for walletConfiguration file + Examples: + | wallet_name | + | TestAutomationWallet | diff --git a/packages/e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature b/packages/e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature index fc24be3f11..2783c4a802 100644 --- a/packages/e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature +++ b/packages/e2e-tests/src/features/e2e/StakingInitialFundsE2E.feature @@ -3,7 +3,7 @@ Feature: Delegating funds to new pool E2E @LW-2685 @Smoke Scenario: Extended view - Staking - Delegating funds to new pool (if not staked yet) E2E. - Given I create new wallet and save wallet information + Given I create new wallet with name: "newCreatedWallet" and save wallet information And Wallet is synced When I open header menu Then I don't see any toast message diff --git a/packages/e2e-tests/src/hooks/beforeTagHooks.ts b/packages/e2e-tests/src/hooks/beforeTagHooks.ts index dace597a38..edab6087ea 100644 --- a/packages/e2e-tests/src/hooks/beforeTagHooks.ts +++ b/packages/e2e-tests/src/hooks/beforeTagHooks.ts @@ -29,7 +29,7 @@ Before({ tags: '@pending or @Pending' }, async () => 'skipped'); Before( { - tags: '@OnboardingCreateWallet or @Staking-initial-E2E or @OnboardingRestoreWallet or @OnboardingHardwareWallet or @TrezorOnboarding or @OnboardingCreatePaperWallet or @OnboardingRestorePaperWallet' + tags: '@OnboardingCreateWallet or @Staking-initial-E2E or @OnboardingRestoreWallet or @OnboardingHardwareWallet or @TrezorOnboarding or @OnboardingCreatePaperWallet or @OnboardingRestorePaperWallet or @WalletMaintenance' }, async () => { await extendedView.visit(); diff --git a/packages/e2e-tests/src/pageobject/newTransactionExtendedPageObject.ts b/packages/e2e-tests/src/pageobject/newTransactionExtendedPageObject.ts index bfc958669c..e3138967af 100644 --- a/packages/e2e-tests/src/pageobject/newTransactionExtendedPageObject.ts +++ b/packages/e2e-tests/src/pageobject/newTransactionExtendedPageObject.ts @@ -5,6 +5,7 @@ import extensionUtils from '../utils/utils'; import { byron, shelley } from '../data/AddressData'; import { AssetInput } from '../elements/newTransaction/assetInput'; import { AddressInput } from '../elements/AddressInput'; +import CommonDrawerElements from '../elements/CommonDrawerElements'; export default new (class NewTransactionExtendedPageObject { async setTwoAssetsForBundle(bundleIndex: number, assetValue1: number, assetValue2: number) { @@ -64,13 +65,17 @@ export default new (class NewTransactionExtendedPageObject { await TokenSelectionPage.clickTokensButton(); const tokens = await TokenSelectionPage.getTokensInfo(); let tokensCount = tokens.length; - for (const token of tokens) { - tokensCount--; - await TokenSelectionPage.clickOnToken(token.name); - if (tokensCount) { - await new AssetInput(bundleIndex).clickAddAssetButton(); - await TokenSelectionPage.clickTokensButton(); + if (tokensCount > 0) { + for (const token of tokens) { + tokensCount--; + await TokenSelectionPage.clickOnToken(token.name); + if (tokensCount) { + await new AssetInput(bundleIndex).clickAddAssetButton(); + await TokenSelectionPage.clickTokensButton(); + } } + } else { + await new CommonDrawerElements().clickHeaderBackButton(); } } diff --git a/packages/e2e-tests/src/steps/commonSteps.ts b/packages/e2e-tests/src/steps/commonSteps.ts index 3f82f960f8..577410abbc 100755 --- a/packages/e2e-tests/src/steps/commonSteps.ts +++ b/packages/e2e-tests/src/steps/commonSteps.ts @@ -197,6 +197,7 @@ Then(/^I open wallet: "([^"]*)" in: (extended|popup) mode$/, async (walletName: await localStorageInitializer.initialiseBasicLocalStorageData(walletName); await localStorageInitializer.initializeShowMultiAddressDiscoveryModal(false); + await localStorageInitializer.disableShowingMultidelegationBetaBanner(); if (mode === 'popup') { await popupView.visit(); } diff --git a/packages/e2e-tests/src/steps/onboardingSteps.ts b/packages/e2e-tests/src/steps/onboardingSteps.ts index a6405721ed..f85eb8f279 100644 --- a/packages/e2e-tests/src/steps/onboardingSteps.ts +++ b/packages/e2e-tests/src/steps/onboardingSteps.ts @@ -35,6 +35,7 @@ import SecureYourPaperWalletPage from '../elements/onboarding/SecureYourPaperWal import SaveYourPaperWalletPageAssert from '../assert/onboarding/SaveYourPaperWalletPageAssert'; import SaveYourPaperWalletPage from '../elements/onboarding/SaveYourPaperWalletPage'; import ScanYourPrivateQrCodePageAssert from '../assert/onboarding/ScanYourPrivateQrCodePageAssert'; +import LocalStorageInitializer from '../fixture/localStorageInitializer'; const mnemonicWords: string[] = getTestWallet(TestWalletName.TestAutomationWallet).mnemonic ?? []; const invalidMnemonicWords: string[] = getTestWallet(TestWalletName.InvalidMnemonic).mnemonic ?? []; @@ -194,13 +195,13 @@ Then(/^I do not see autocomplete options list$/, async () => { await onboardingRecoveryPhrasePageAssert.assertNotSeeMnemonicAutocompleteOptions(); }); -Given(/^I create new wallet and save wallet information$/, async () => { - // issue LW-11288 - please remove when it will be fixed / check on CI is needed +Given(/^I create new wallet with name: "([^"]*)" and save wallet information$/, async (walletName: string) => { await browser.pause(1000); await OnboardingMainPage.createWalletButton.click(); - await OnboardingWalletSetupPage.goToWalletSetupPage('Create', mnemonicWords, true); + await OnboardingWalletSetupPage.goToWalletSetupPage('Create', mnemonicWords, true, walletName, 'default'); await OnboardingWalletSetupPageAssert.assertSeeWalletSetupPage(); await OnboardingWalletSetupPage.clickEnterWalletButton(); + await LocalStorageInitializer.disableShowPinExtension(); await TopNavigationAssert.assertLogoPresent(); await settingsExtendedPageObject.switchNetworkAndCloseDrawer('Preprod', 'extended'); const newCreatedWallet = JSON.stringify(await getWalletsFromRepository()); @@ -258,8 +259,12 @@ Given( /^I enter wallet name: "([^"]*)", password: "([^"]*)" and password confirmation: "([^"]*)"$/, async (walletName: string, password: string, passwordConfirmation: string) => { await OnboardingWalletSetupPage.setWalletNameInput(walletName); - await OnboardingWalletSetupPage.setWalletPasswordInput(password); - await OnboardingWalletSetupPage.setWalletPasswordConfirmInput(passwordConfirmation); + await OnboardingWalletSetupPage.setWalletPasswordInput( + password === 'default' ? String(process.env.WALLET_1_PASSWORD) : password + ); + await OnboardingWalletSetupPage.setWalletPasswordConfirmInput( + passwordConfirmation === 'default' ? String(process.env.WALLET_1_PASSWORD) : passwordConfirmation + ); } ); diff --git a/packages/e2e-tests/src/steps/sendTransactionSimpleSteps.ts b/packages/e2e-tests/src/steps/sendTransactionSimpleSteps.ts index b54d550165..74fea980df 100644 --- a/packages/e2e-tests/src/steps/sendTransactionSimpleSteps.ts +++ b/packages/e2e-tests/src/steps/sendTransactionSimpleSteps.ts @@ -46,6 +46,7 @@ import { parseWalletAddress } from '../utils/parseWalletAddress'; import { AddressType } from '../enums/AddressTypeEnum'; import clipboard from 'clipboardy'; import walletAddressPage from '../elements/walletAddressPage'; +import { CoinConfigure } from '../elements/newTransaction/coinConfigure'; Given(/I have several contacts whose start with the same characters/, async () => { await indexedDB.clearAddressBook(); @@ -146,6 +147,13 @@ When(/^I select amount: (\d*) of asset type: (Tokens|NFTs)$/, async (amount: num await TokenSelectionPage.addAmountOfAssets(amount, assetType); }); +When(/^I click MAX button for all selected tokens$/, async () => { + const tokenNames = await new CoinConfigure(1).getAllTokenNames(); + for (const tokenName of tokenNames) { + await new CoinConfigure(1, tokenName).clickMaxButton(); + } +}); + When(/^I deselect (Tokens|NFTs) (\d*)$/, async (assetType: 'Tokens' | 'NFTs', index: number) => { await TokenSelectionPage.deselectToken(assetType, index); }); @@ -256,6 +264,11 @@ When(/^I fill bundle with copied address and ([^"]*) ADA$/, async (adaValue: str await TransactionNewPage.coinConfigure(1, Asset.CARDANO.ticker).fillTokenValue(Number.parseFloat(adaValue)); }); +When(/^I fill address input with copied address$/, async () => { + const addressInput = new AddressInput(1); + await addressInput.fillAddress(await clipboard.read()); +}); + When(/^I fill bundle with saved unused address and ([^"]*) ADA$/, async (adaValue: string) => { const addressInput = new AddressInput(1); await addressInput.fillAddress(await walletAddressPage.getSavedLastAddress()); diff --git a/packages/e2e-tests/src/steps/transactionsSteps.ts b/packages/e2e-tests/src/steps/transactionsSteps.ts index 3af7ebfee6..1a6f02cb89 100644 --- a/packages/e2e-tests/src/steps/transactionsSteps.ts +++ b/packages/e2e-tests/src/steps/transactionsSteps.ts @@ -255,3 +255,7 @@ Then(/^I save tx hash value "([^"]*)"$/, async (hash: string) => { Logger.log(`saving tx hash: ${hash}`); testContext.save('txHashValue', hash); }); + +Then(/^Transactions counter is showing value higher than (\d+)$/, async (transactionsMaxNumber: number) => { + await transactionsPageAssert.assertCounterShowingMoreTransactionsThan(transactionsMaxNumber); +}); diff --git a/packages/e2e-tests/src/steps/walletMaintenanceSteps.ts b/packages/e2e-tests/src/steps/walletMaintenanceSteps.ts new file mode 100644 index 0000000000..cf62ac3647 --- /dev/null +++ b/packages/e2e-tests/src/steps/walletMaintenanceSteps.ts @@ -0,0 +1,53 @@ +/* eslint-disable no-console */ +import { Then } from '@wdio/cucumber-framework'; +import { AssetInput } from '../elements/newTransaction/assetInput'; +import testContext from '../utils/testContext'; +import { WalletRepositoryConfig, Account } from '../support/walletConfiguration'; +import { Logger } from '../support/logger'; +import NewTransactionExtendedPageObject from '../pageobject/newTransactionExtendedPageObject'; + +Then( + /^If available: I add all available (Token|NFT) types to bundle (\d*)$/, + async (typeOfAsset: 'Token' | 'NFT', bundleIndex: number) => { + const assetInput = new AssetInput(bundleIndex); + await assetInput.assetAddButton.waitForStable(); + if (await assetInput.assetAddButton.isEnabled()) { + await (typeOfAsset === 'Token' + ? NewTransactionExtendedPageObject.addAllAvailableTokenTypes(bundleIndex) + : NewTransactionExtendedPageObject.addAllAvailableNftTypes(bundleIndex)); + } else { + Logger.log('NFTs not available, skipping step'); + } + } +); + +Then(/^I print wallet "([^"]*)" data for walletConfiguration file$/, async (walletName: string) => { + const walletMnemonic: string = testContext.load('newCreatedWalletMnemonic'); + const walletRepositoryData: string = testContext.load('newCreatedWallet'); + let stakePoolsToDelegate = ''; + try { + stakePoolsToDelegate = testContext.load('stakePoolsInUse'); + } catch (error) { + console.log(error); + } + + const jsonData = JSON.parse(walletRepositoryData); + + const account: Account = {} as Account; + account.accountNumber = 0; + account.address = jsonData[0].metadata.walletAddresses[1]; + account.mainnetAddress = jsonData[0].metadata.walletAddresses[0]; + account.publicKey = jsonData[0].accounts[0].extendedAccountPublicKey; + + const newData: WalletRepositoryConfig = {} as WalletRepositoryConfig; + newData.mnemonic = walletMnemonic.split(' '); + newData.name = `TestWalletName.${walletName}`; + newData.password = 'process.env.WALLET_1_PASSWORD'; + newData.accounts = []; + newData.accounts.push(account); + newData.repository = walletRepositoryData; + + console.log(newData); + console.log(`mnemonic: '${walletMnemonic}'.split('')`); + console.log(`stake pools for delegation: ${JSON.stringify(stakePoolsToDelegate)}`); +});