<NME> leumi.ts
<BEF> import moment, { Moment } from 'moment';
import { Page } from 'puppeteer';
import { BaseScraperWithBrowser, LoginResults, LoginOptions } from './base-scraper-with-browser';
import {
  dropdownSelect,
  dropdownElements,
  fillInput,
  clickButton,
  waitUntilElementFound,
  pageEvalAll,
  elementPresentOnPage,
} from '../helpers/elements-interactions';
import { waitForNavigation } from '../helpers/navigation';
import { SHEKEL_CURRENCY } from '../constants';
import {
  TransactionsAccount, Transaction, TransactionStatuses, TransactionTypes,
} from '../transactions';
import { ScaperScrapingResult, ScraperCredentials } from './base-scraper';

const BASE_URL = 'https://hb2.bankleumi.co.il';
const DATE_FORMAT = 'DD/MM/YY';
const NO_TRANSACTION_IN_DATE_RANGE_TEXT = 'לא קיימות תנועות מתאימות על פי הסינון שהוגדר';
const ACCOUNT_BLOCKED_MSG = 'המנוי חסום';

function getTransactionsUrl() {
  return `${BASE_URL}/ebanking/Accounts/ExtendedActivity.aspx?WidgetPar=1#/`;
}

function getPossibleLoginResults() {
  const urls: LoginOptions['possibleResults'] = {};

function getPossibleLoginResults() {
  const urls: LoginOptions['possibleResults'] = {
    [LoginResults.Success]: [/ebanking\/SO\/SPA.aspx/i],
    [LoginResults.InvalidPassword]: [
      async (options) => {
        if (!options || !options.page) {
          throw new Error('missing page options argument');
        }
        const errorMessage = await pageEvalAll(options.page, 'svg#Capa_1', '', (element) => {
          return (element[0]?.parentElement?.children[1] as HTMLDivElement)?.innerText;
        });

        return errorMessage?.startsWith(INVALID_PASSWORD_MSG);
      },
    ],
    [LoginResults.AccountBlocked]: [ // NOTICE - might not be relevant starting the Leumi re-design during 2022 Sep
      async (options) => {
        if (!options || !options.page) {
          throw new Error('missing page options argument');
  ];
}

function getAmountData(amountStr: string) {
  const amountStrCopy = amountStr.replace(',', '');
  const amount = parseFloat(amountStrCopy);
  const currency = SHEKEL_CURRENCY;

  return {
    amount,
    currency,
  };
}

interface ScrapedTransaction {
  status: TransactionStatuses;
  description?: string;
  memo?: string;
  balance?: string;
  credit?: string;
  debit?: string;
  reference?: string;
  date?: string;
}

function convertTransactions(txns: ScrapedTransaction[]): Transaction[] {
  return txns.map((txn) => {
    const txnDate = moment(txn.date, DATE_FORMAT).toISOString();

    const credit = getAmountData(txn.credit || '').amount;
    const debit = getAmountData(txn.debit || '').amount;
    const amount = (Number.isNaN(credit) ? 0 : credit) - (Number.isNaN(debit) ? 0 : debit);

    const transaction: Transaction = {
      type: TransactionTypes.Normal,
      identifier: txn.reference ? parseInt(txn.reference, 10) : undefined,
      date: txnDate,
      processedDate: txnDate,
      originalAmount: amount,
      originalCurrency: SHEKEL_CURRENCY,
      chargedAmount: amount,
      status: txn.status,
      description: txn.description || '',
      memo: txn.memo || '',
    };
    return transaction;
  });
}
interface ScrapedTds {
  classList: string;
  innerText: string;
}

async function extractCompletedTransactionsFromPage(page: Page): Promise<ScrapedTransaction[]> {
  const txns: ScrapedTransaction[] = [];
  const tdsValues = await pageEvalAll<ScrapedTds[]>(page, '#WorkSpaceBox #ctlActivityTable tr td', [], (tds) => {
    return tds.map((td) => ({
      classList: td.getAttribute('class') || '',
      innerText: (td as HTMLElement).innerText,
    }));
  });

  for (const element of tdsValues) {
    if (element.classList.includes('ExtendedActivityColumnDate')) {
      const newTransaction: ScrapedTransaction = { status: TransactionStatuses.Completed };
      newTransaction.date = (element.innerText || '').trim();
      txns.push(newTransaction);
    } else {
      const changedTransaction = txns.length ? txns.pop() : null;
      if (changedTransaction) {
        if (element.classList.includes('ActivityTableColumn1LTR') || element.classList.includes('ActivityTableColumn1')) {
          changedTransaction.description = element.innerText;
        } else if (element.classList.includes('ReferenceNumberUniqeClass')) {
          changedTransaction.reference = element.innerText;
        } else if (element.classList.includes('AmountDebitUniqeClass')) {
          changedTransaction.debit = element.innerText;
        } else if (element.classList.includes('AmountCreditUniqeClass')) {
          changedTransaction.credit = element.innerText;
        } else if (element.classList.includes('number_column')) {
          changedTransaction.balance = element.innerText;
        } else if (element.classList.includes('tdDepositRowAdded')) {
          changedTransaction.memo = (element.innerText || '').trim();
        }
        txns.push(changedTransaction);
      }
    }
  }

  return txns;
}

async function extractPendingTransactionsFromPage(page: Page): Promise<ScrapedTransaction[]> {
  const txns: ScrapedTransaction[] = [];
  const tdsValues = await pageEvalAll<ScrapedTds[]>(page, '#WorkSpaceBox table#ctlTodayActivityTableUpper tr td', [], (tds) => {
    return tds.map((td) => ({
      classList: td.getAttribute('class') || '',
      innerText: (td as HTMLElement).innerText,
    }));
  });

  for (const element of tdsValues) {
    if (element.classList.includes('Colume1Width')) {
      const newTransaction: ScrapedTransaction = { status: TransactionStatuses.Pending };
      newTransaction.date = (element.innerText || '').trim();
      txns.push(newTransaction);
    } else {
      const changedTransaction = txns.length ? txns.pop() : null;

      if (changedTransaction) {
        if (element.classList.includes('Colume2Width')) {
          changedTransaction.description = element.innerText;
        } else if (element.classList.includes('Colume3Width')) {
          changedTransaction.reference = element.innerText;
        } else if (element.classList.includes('Colume4Width')) {
          changedTransaction.debit = element.innerText;
        } else if (element.classList.includes('Colume5Width')) {
          changedTransaction.credit = element.innerText;
        } else if (element.classList.includes('Colume6Width')) {
          changedTransaction.balance = element.innerText;
        }
        txns.push(changedTransaction);
      }
    }
  }

  return txns;
}

async function isNoTransactionInDateRangeError(page: Page) {
  const hasErrorInfoElement = await elementPresentOnPage(page, '.errInfo');
  if (hasErrorInfoElement) {
    const errorText = await page.$eval('.errInfo', (errorElement) => {
      return (errorElement as HTMLElement).innerText;
    });
    return errorText === NO_TRANSACTION_IN_DATE_RANGE_TEXT;
  }
  return false;
}

async function fetchTransactionsForAccount(page: Page, startDate: Moment, accountId: string): Promise<TransactionsAccount> {
  await dropdownSelect(page, 'select#ddlAccounts_m_ddl', accountId);
  await dropdownSelect(page, 'select#ddlTransactionPeriod', '004');
  await waitUntilElementFound(page, 'select#ddlTransactionPeriod');
  await fillInput(
    page,
    'input#dtFromDate_textBox',
    startDate.format(DATE_FORMAT),
  );
  await clickButton(page, 'input#btnDisplayDates');
  await waitForNavigation(page);

  const selectedSnifAccount = await page.$eval('#ddlAccounts_m_ddl option[selected="selected"]', (option) => {
    return (option as HTMLElement).innerText;
  });

  const accountNumber = selectedSnifAccount.replace('/', '_');

  const balanceValue = await page.$eval('#lblBalancesVal', (element) => element.textContent);
  const balance = balanceValue ? parseFloat(balanceValue.replace(/[^\d.]/g, '')) : undefined;

  await Promise.race([
    waitUntilElementFound(page, 'table#WorkSpaceBox table#ctlActivityTable', false),
    waitUntilElementFound(page, '.errInfo', false),
  ]);

  if (await isNoTransactionInDateRangeError(page)) {
    return {
      accountNumber,
      balance,
      txns: [],
    };
  }

  const hasExpandAllButton = await elementPresentOnPage(page, 'a#lnkCtlExpandAllInPage');

  if (hasExpandAllButton) {
    await clickButton(page, 'a#lnkCtlExpandAllInPage');
  }

  const pendingTxns = await extractPendingTransactionsFromPage(page);
  const completedTxns = await extractCompletedTransactionsFromPage(page);
  const txns = [
    ...pendingTxns,
    ...completedTxns,
async function fetchTransactionsForAccount(page: Page, startDate: Moment, accountId: string): Promise<TransactionsAccount> {

  return {
    accountNumber,
    txns: convertTransactions(txns),
  };
}

async function fetchTransactions(page: Page, startDate: Moment) {
  const res: TransactionsAccount[] = [];
  // Loop through all available accounts and collect transactions from all
  const accounts = await dropdownElements(page, 'select#ddlAccounts_m_ddl');
  for (const account of accounts) {
    // Skip "All accounts" option
    if (account.value !== '-1') {
      res.push(await fetchTransactionsForAccount(page, startDate, account.value));
    }
  }
  return res;
}

async function waitForPostLogin(page: Page): Promise<void> {
  // DEVELOPER NOTICE the account number received from the server is being altered at
  // runtime for some accounts after 1-2 seconds so we need to hang the process for a short while.
  await hangProcess(4000);

  const accountsIds = await page.evaluate(() => Array.from(document.querySelectorAll('app-masked-number-combo span.display-number-li'), (e) => e.textContent)) as string[];

  // due to a bug, the altered value might include undesired signs like & that should be removed

  if (!accountsIds.length) {
    throw new Error('Failed to extract or parse the account number');
  }

  for (const accountId of accountsIds) {
    if (accountsIds.length > 1) {
      // get list of accounts and check accountId
      await clickByXPath(page, '//*[contains(@class, "number") and contains(@class, "combo-inner")]');
      await clickByXPath(page, `//span[contains(text(), '${accountId}')]`);
    }

    accounts.push(await fetchTransactionsForAccount(page, startDate, removeSpecialCharacters(accountId)));
  }
    const startDate = this.options.startDate || defaultStartMoment.toDate();
    const startMoment = moment.max(defaultStartMoment, moment(startDate));

    const url = getTransactionsUrl();
    await this.navigateTo(url);

    const accounts = await fetchTransactions(this.page, startMoment);

  await waitUntilElementFound(page, loginButtonSelector);
  await clickButton(page, loginButtonSelector);
  await waitForNavigation(page, { waitUntil: 'networkidle2' });
  await Promise.all([
    waitUntilElementFound(page, 'input[placeholder="שם משתמש"]', true),
    waitUntilElementFound(page, 'input[placeholder="סיסמה"]', true),
    waitUntilElementFound(page, 'button[type="submit"]', true),
  ]);
}

async function waitForPostLogin(page: Page): Promise<void> {
  await Promise.race([
    waitUntilElementFound(page, 'a[title="דלג לחשבון"]', true, 60000),
    waitUntilElementFound(page, 'div.leumi-container', true, 60000),
    page.waitForXPath(`//div[contains(string(),"${INVALID_PASSWORD_MSG}")]`),
    waitUntilElementFound(page, 'form[action="/changepassword"]', true, 60000), // not sure if they kept this one
  ]);
}

class LeumiScraper extends BaseScraperWithBrowser {
  getLoginOptions(credentials: Record<string, string>) {
    return {
      loginUrl: LOGIN_URL,
      fields: createLoginFields(credentials),
      submitButtonSelector: "button[type='submit']",
      checkReadiness: async () => navigateToLogin(this.page),
      postAction: async () => waitForPostLogin(this.page),
      possibleResults: getPossibleLoginResults(),
    };
  }

  async fetchData(): Promise<ScaperScrapingResult> {
    const minimumStartMoment = moment().subtract(3, 'years').add(1, 'day');
    const defaultStartMoment = moment().subtract(1, 'years').add(1, 'day');
    const startDate = this.options.startDate || defaultStartMoment.toDate();
    const startMoment = moment.max(minimumStartMoment, moment(startDate));

    await this.navigateTo(TRANSACTIONS_URL);

    const accounts = await fetchTransactions(this.page, startMoment);

    return {
      success: true,
      accounts,
    };
  }
}

export default LeumiScraper;

<MSG> fix leumi scraper

<DFF> @@ -2,15 +2,11 @@ import moment, { Moment } from 'moment';
 import { Page } from 'puppeteer';
 import { BaseScraperWithBrowser, LoginResults, LoginOptions } from './base-scraper-with-browser';
 import {
-  dropdownSelect,
-  dropdownElements,
   fillInput,
   clickButton,
   waitUntilElementFound,
   pageEvalAll,
-  elementPresentOnPage,
 } from '../helpers/elements-interactions';
-import { waitForNavigation } from '../helpers/navigation';
 import { SHEKEL_CURRENCY } from '../constants';
 import {
   TransactionsAccount, Transaction, TransactionStatuses, TransactionTypes,
@@ -18,13 +14,12 @@ import {
 import { ScaperScrapingResult, ScraperCredentials } from './base-scraper';
 
 const BASE_URL = 'https://hb2.bankleumi.co.il';
-const DATE_FORMAT = 'DD/MM/YY';
-const NO_TRANSACTION_IN_DATE_RANGE_TEXT = 'לא קיימות תנועות מתאימות על פי הסינון שהוגדר';
+const TRANSACTIONS_URL = `${BASE_URL}/eBanking/SO/SPA.aspx#/ts/BusinessAccountTrx?WidgetPar=1`;
+const FILTERED_TRANSACTIONS_URL = `${BASE_URL}/ChannelWCF/Broker.svc/ProcessRequest?moduleName=UC_SO_27_GetBusinessAccountTrx`;
+
+const DATE_FORMAT = 'DD.MM.YY';
 const ACCOUNT_BLOCKED_MSG = 'המנוי חסום';
 
-function getTransactionsUrl() {
-  return `${BASE_URL}/ebanking/Accounts/ExtendedActivity.aspx?WidgetPar=1#/`;
-}
 
 function getPossibleLoginResults() {
   const urls: LoginOptions['possibleResults'] = {};
@@ -51,184 +46,64 @@ function createLoginFields(credentials: ScraperCredentials) {
   ];
 }
 
-function getAmountData(amountStr: string) {
-  const amountStrCopy = amountStr.replace(',', '');
-  const amount = parseFloat(amountStrCopy);
-  const currency = SHEKEL_CURRENCY;
-
-  return {
-    amount,
-    currency,
-  };
-}
-
-interface ScrapedTransaction {
-  status: TransactionStatuses;
-  description?: string;
-  memo?: string;
-  balance?: string;
-  credit?: string;
-  debit?: string;
-  reference?: string;
-  date?: string;
-}
-
-function convertTransactions(txns: ScrapedTransaction[]): Transaction[] {
-  return txns.map((txn) => {
-    const txnDate = moment(txn.date, DATE_FORMAT).toISOString();
-
-    const credit = getAmountData(txn.credit || '').amount;
-    const debit = getAmountData(txn.debit || '').amount;
-    const amount = (Number.isNaN(credit) ? 0 : credit) - (Number.isNaN(debit) ? 0 : debit);
+function extractTransactionsFromPage(transactions: any[], status: TransactionStatuses): Transaction[] {
+  if (transactions === null || transactions.length === 0) {
+    return [];
+  }
 
-    const transaction: Transaction = {
+  const result: Transaction[] = transactions.map(rawTransaction => {
+    const newTransaction: Transaction = {
+      status,
       type: TransactionTypes.Normal,
-      identifier: txn.reference ? parseInt(txn.reference, 10) : undefined,
-      date: txnDate,
-      processedDate: txnDate,
-      originalAmount: amount,
+      date: rawTransaction.DateUTC,
+      processedDate: rawTransaction.DateUTC,
+      description: rawTransaction.Description || '',
+      identifier: rawTransaction.ReferenceNumberLong,
+      memo: rawTransaction.AdditionalData || '',
       originalCurrency: SHEKEL_CURRENCY,
-      chargedAmount: amount,
-      status: txn.status,
-      description: txn.description || '',
-      memo: txn.memo || '',
+      chargedAmount: rawTransaction.Amount,
+      originalAmount: rawTransaction.Amount,
     };
-    return transaction;
-  });
-}
-interface ScrapedTds {
-  classList: string;
-  innerText: string;
-}
 
-async function extractCompletedTransactionsFromPage(page: Page): Promise<ScrapedTransaction[]> {
-  const txns: ScrapedTransaction[] = [];
-  const tdsValues = await pageEvalAll<ScrapedTds[]>(page, '#WorkSpaceBox #ctlActivityTable tr td', [], (tds) => {
-    return tds.map((td) => ({
-      classList: td.getAttribute('class') || '',
-      innerText: (td as HTMLElement).innerText,
-    }));
-  });
+    return newTransaction;
+  })
 
-  for (const element of tdsValues) {
-    if (element.classList.includes('ExtendedActivityColumnDate')) {
-      const newTransaction: ScrapedTransaction = { status: TransactionStatuses.Completed };
-      newTransaction.date = (element.innerText || '').trim();
-      txns.push(newTransaction);
-    } else {
-      const changedTransaction = txns.length ? txns.pop() : null;
-      if (changedTransaction) {
-        if (element.classList.includes('ActivityTableColumn1LTR') || element.classList.includes('ActivityTableColumn1')) {
-          changedTransaction.description = element.innerText;
-        } else if (element.classList.includes('ReferenceNumberUniqeClass')) {
-          changedTransaction.reference = element.innerText;
-        } else if (element.classList.includes('AmountDebitUniqeClass')) {
-          changedTransaction.debit = element.innerText;
-        } else if (element.classList.includes('AmountCreditUniqeClass')) {
-          changedTransaction.credit = element.innerText;
-        } else if (element.classList.includes('number_column')) {
-          changedTransaction.balance = element.innerText;
-        } else if (element.classList.includes('tdDepositRowAdded')) {
-          changedTransaction.memo = (element.innerText || '').trim();
-        }
-        txns.push(changedTransaction);
-      }
-    }
-  }
-
-  return txns;
+  return result;
 }
 
-async function extractPendingTransactionsFromPage(page: Page): Promise<ScrapedTransaction[]> {
-  const txns: ScrapedTransaction[] = [];
-  const tdsValues = await pageEvalAll<ScrapedTds[]>(page, '#WorkSpaceBox table#ctlTodayActivityTableUpper tr td', [], (tds) => {
-    return tds.map((td) => ({
-      classList: td.getAttribute('class') || '',
-      innerText: (td as HTMLElement).innerText,
-    }));
-  });
-
-  for (const element of tdsValues) {
-    if (element.classList.includes('Colume1Width')) {
-      const newTransaction: ScrapedTransaction = { status: TransactionStatuses.Pending };
-      newTransaction.date = (element.innerText || '').trim();
-      txns.push(newTransaction);
-    } else {
-      const changedTransaction = txns.length ? txns.pop() : null;
-
-      if (changedTransaction) {
-        if (element.classList.includes('Colume2Width')) {
-          changedTransaction.description = element.innerText;
-        } else if (element.classList.includes('Colume3Width')) {
-          changedTransaction.reference = element.innerText;
-        } else if (element.classList.includes('Colume4Width')) {
-          changedTransaction.debit = element.innerText;
-        } else if (element.classList.includes('Colume5Width')) {
-          changedTransaction.credit = element.innerText;
-        } else if (element.classList.includes('Colume6Width')) {
-          changedTransaction.balance = element.innerText;
-        }
-        txns.push(changedTransaction);
-      }
-    }
-  }
-
-  return txns;
-}
-
-async function isNoTransactionInDateRangeError(page: Page) {
-  const hasErrorInfoElement = await elementPresentOnPage(page, '.errInfo');
-  if (hasErrorInfoElement) {
-    const errorText = await page.$eval('.errInfo', (errorElement) => {
-      return (errorElement as HTMLElement).innerText;
-    });
-    return errorText === NO_TRANSACTION_IN_DATE_RANGE_TEXT;
-  }
-  return false;
-}
 
 async function fetchTransactionsForAccount(page: Page, startDate: Moment, accountId: string): Promise<TransactionsAccount> {
-  await dropdownSelect(page, 'select#ddlAccounts_m_ddl', accountId);
-  await dropdownSelect(page, 'select#ddlTransactionPeriod', '004');
-  await waitUntilElementFound(page, 'select#ddlTransactionPeriod');
+  await waitUntilElementFound(page, 'button[title="חיפוש מתקדם"]', true);
+  await clickButton(page, 'button[title="חיפוש מתקדם"]');
+  await clickButton(page, '#bll-radio-3');
+  await waitUntilElementFound(page, 'input[formcontrolname="txtInputFrom"]', true);
+
   await fillInput(
-    page,
-    'input#dtFromDate_textBox',
-    startDate.format(DATE_FORMAT),
+      page,
+      'input[formcontrolname="txtInputFrom"]',
+      startDate.format(DATE_FORMAT),
   );
-  await clickButton(page, 'input#btnDisplayDates');
-  await waitForNavigation(page);
 
-  const selectedSnifAccount = await page.$eval('#ddlAccounts_m_ddl option[selected="selected"]', (option) => {
-    return (option as HTMLElement).innerText;
-  });
+  // we must blur the from control otherwise the search will use the previous value
+  await page.focus("button[aria-label='סנן']");
 
-  const accountNumber = selectedSnifAccount.replace('/', '_');
-
-  const balanceValue = await page.$eval('#lblBalancesVal', (element) => element.textContent);
-  const balance = balanceValue ? parseFloat(balanceValue.replace(/[^\d.]/g, '')) : undefined;
-
-  await Promise.race([
-    waitUntilElementFound(page, 'table#WorkSpaceBox table#ctlActivityTable', false),
-    waitUntilElementFound(page, '.errInfo', false),
-  ]);
+  await clickButton(page, "button[aria-label='סנן']");
+  const finalResponse = await page.waitForResponse(response => {
+    return response.url() === FILTERED_TRANSACTIONS_URL
+        && response.request().method() === 'POST';
+  });
 
-  if (await isNoTransactionInDateRangeError(page)) {
-    return {
-      accountNumber,
-      balance,
-      txns: [],
-    };
-  }
+  let responseJson: any = await finalResponse.json();
 
-  const hasExpandAllButton = await elementPresentOnPage(page, 'a#lnkCtlExpandAllInPage');
+  const accountNumber = accountId;
+  const response = JSON.parse(responseJson.jsonResp);
 
-  if (hasExpandAllButton) {
-    await clickButton(page, 'a#lnkCtlExpandAllInPage');
-  }
+  const pendingTransactions = response.TodayTransactionsItems;
+  const transactions = response.HistoryTransactionsItems;
+  const balance = response.BalanceDisplay ? parseFloat(response.BalanceDisplay) : undefined;
 
-  const pendingTxns = await extractPendingTransactionsFromPage(page);
-  const completedTxns = await extractCompletedTransactionsFromPage(page);
+  const pendingTxns = extractTransactionsFromPage(pendingTransactions, TransactionStatuses.Pending);
+  const completedTxns = extractTransactionsFromPage(transactions, TransactionStatuses.Completed);
   const txns = [
     ...pendingTxns,
     ...completedTxns,
@@ -236,21 +111,53 @@ async function fetchTransactionsForAccount(page: Page, startDate: Moment, accoun
 
   return {
     accountNumber,
-    txns: convertTransactions(txns),
+    balance,
+    txns,
   };
 }
 
-async function fetchTransactions(page: Page, startDate: Moment) {
-  const res: TransactionsAccount[] = [];
-  // Loop through all available accounts and collect transactions from all
-  const accounts = await dropdownElements(page, 'select#ddlAccounts_m_ddl');
-  for (const account of accounts) {
-    // Skip "All accounts" option
-    if (account.value !== '-1') {
-      res.push(await fetchTransactionsForAccount(page, startDate, account.value));
-    }
+function hangProcess(timeout: number) {
+  return new Promise((resolve) => {
+    setTimeout(() => {
+      resolve();
+    }, timeout)
+  })
+}
+async function fetchTransactions(page: Page, startDate: Moment): Promise<TransactionsAccount[]> {
+  // TODO should adjust logic to support multiple accounts (I don't have such an account)
+
+  // DEVELOPER NOTICE the account number received from the server is being altered at runtime for some accounts
+  // after 1-2 seconds so we need to hang the process for a short while.
+  await hangProcess(4000);
+
+  const accountSpanText = await page.$eval('app-masked-number-combo span.display-number-li', (span: any) => {
+    return span.textContent;
+  });
+
+  // due to a bug, the altered value might include undesired signs like & that are removed here
+  const accountNumberMatches = accountSpanText.match(/\d+-\d+(\/)?\d+/);
+  const account = accountNumberMatches ? accountNumberMatches[0] : null;
+
+  if (!account) {
+    throw new Error('Failed to extract or parse the account number');
   }
-  return res;
+
+  return [
+      await fetchTransactionsForAccount(page, startDate, account)
+  ]
+  return new Promise((resolve) => {
+    setTimeout(() => {
+
+
+      if (!account) {
+        throw new Error('failed to extract account number');
+      }
+      resolve([
+
+      ]);
+    }, 5000);
+  })
+
 }
 
 async function waitForPostLogin(page: Page): Promise<void> {
@@ -278,8 +185,7 @@ class LeumiScraper extends BaseScraperWithBrowser {
     const startDate = this.options.startDate || defaultStartMoment.toDate();
     const startMoment = moment.max(defaultStartMoment, moment(startDate));
 
-    const url = getTransactionsUrl();
-    await this.navigateTo(url);
+    await this.navigateTo(TRANSACTIONS_URL);
 
     const accounts = await fetchTransactions(this.page, startMoment);
 

fix leumi scraper