diff --git a/wallets/keplr/src/KeplrWallet.ts b/wallets/keplr/src/KeplrWallet.ts
new file mode 100644
index 000000000..b6e47aba1
--- /dev/null
+++ b/wallets/keplr/src/KeplrWallet.ts
@@ -0,0 +1,143 @@
+import type { Page } from '@playwright/test'
+export type Keplr = 'keplr'
+
+export class KeplrWallet {
+ seedPhrase = ''
+ wallet: Keplr = 'keplr'
+
+ constructor(readonly page: Page) {
+ this.page = page
+ }
+
+ /**
+ * Imports wallet from secret phrase and password.
+ *
+ * @param secretWords. The secret words to import.
+ * @param password. The password to set.
+ *
+ * @returns true if the wallet was imported successfully.
+ */
+ async importWallet(secretWords, password) {
+ await playwright.waitAndClickByText(
+ onboardingElements.createWalletButton,
+ await playwright.keplrWindow(),
+ );
+ await playwright.waitAndClickByText(
+ onboardingElements.importRecoveryPhraseButton,
+ await playwright.keplrWindow(),
+ );
+ await playwright.waitAndClickByText(
+ onboardingElements.useRecoveryPhraseButton,
+ await playwright.keplrWindow(),
+ );
+ await playwright.waitAndClickByText(
+ onboardingElements.phraseCount24,
+ await playwright.keplrWindow(),
+ );
+
+ for (const [index, word] of secretWords.split(' ').entries()) {
+ await playwright.waitAndTypeByLocator(
+ onboardingElements.textAreaSelector,
+ word,
+ index,
+ );
+ }
+
+ await playwright.waitAndClick(
+ onboardingElements.submitPhraseButton,
+ await playwright.keplrWindow(),
+ );
+
+ await playwright.waitAndType(
+ onboardingElements.walletInput,
+ onboardingElements.walletName,
+ );
+ await playwright.waitAndType(onboardingElements.passwordInput, password);
+ await playwright.waitAndType(
+ onboardingElements.confirmPasswordInput,
+ password,
+ );
+
+ await playwright.waitAndClick(
+ onboardingElements.submitWalletDataButton,
+ await playwright.keplrWindow(),
+ { number: 1 },
+ );
+
+ await playwright.waitForByText(
+ onboardingElements.phraseSelectChain,
+ await playwright.keplrWindow(),
+ );
+
+ await playwright.waitAndClick(
+ onboardingElements.submitChainButton,
+ await playwright.keplrWindow(),
+ );
+
+ await playwright.waitForByText(
+ onboardingElements.phraseAccountCreated,
+ await playwright.keplrWindow(),
+ );
+
+ await playwright.waitAndClick(
+ onboardingElements.finishButton,
+ await playwright.keplrWindow(),
+ { dontWait: true },
+ );
+
+ return true;
+ }
+
+ /**
+ * Adds a new account.
+ *
+ * @returns true if the account was added successfully.
+ */
+ async acceptAccess() {
+ const notificationPage = await playwright.switchToKeplrNotification();
+ await playwright.waitAndClick(
+ notificationPageElements.approveButton,
+ notificationPage,
+ { waitForEvent: 'close' },
+ );
+ return true;
+ }
+
+ /**
+ * Confirms a transaction.
+ *
+ * @returns true if the transaction was confirmed successfully.
+ */
+ async confirmTransaction() {
+ const notificationPage = await playwright.switchToKeplrNotification();
+ await playwright.waitAndClick(
+ notificationPageElements.approveButton,
+ notificationPage,
+ { waitForEvent: 'close' },
+ );
+ return true;
+ }
+
+ /**
+ * Does initial setup for the wallet.
+ *
+ * @param playwrightInstance. The playwright instance to use.
+ * @param secretWordsOrPrivateKey. The secret words or private key to import.
+ * @param password. The password to set.
+ */
+ async setupWallet(
+ playwrightInstance,
+ { secretWordsOrPrivateKey, password },
+ ) {
+ if (playwrightInstance) {
+ await playwright.init(playwrightInstance);
+ } else {
+ await playwright.init();
+ }
+
+ await playwright.assignWindows();
+ await playwright.assignActiveTabName('keplr');
+ await module.exports.getExtensionDetails();
+ await module.exports.importWallet(secretWordsOrPrivateKey, password);
+ }
+}
diff --git a/wallets/keplr/src/cypress/errors.ts b/wallets/keplr/src/cypress/errors.ts
new file mode 100644
index 000000000..7d46bf925
--- /dev/null
+++ b/wallets/keplr/src/cypress/errors.ts
@@ -0,0 +1,3 @@
+export const NO_CONTEXT = 'No browser context found. Connect Playwright first - connectPlaywright()'
+export const NO_PAGE = 'No page found. Use getPage()'
+export const MISSING_INIT = 'Keplr not initialized. Use initKeplrWallet()'
diff --git a/wallets/keplr/src/cypress/index.ts b/wallets/keplr/src/cypress/index.ts
new file mode 100644
index 000000000..b06eeeeb6
--- /dev/null
+++ b/wallets/keplr/src/cypress/index.ts
@@ -0,0 +1 @@
+export { default as installSynpress } from './installSynpress'
\ No newline at end of file
diff --git a/wallets/keplr/src/cypress/initKeplrWallet.ts b/wallets/keplr/src/cypress/initKeplrWallet.ts
new file mode 100644
index 000000000..0673ad282
--- /dev/null
+++ b/wallets/keplr/src/cypress/initKeplrWallet.ts
@@ -0,0 +1,77 @@
+import { readFileSync } from 'fs'
+import { type BrowserContext, type Page, chromium } from '@playwright/test'
+
+import { KeplrWallet } from '../KeplrWallet'
+import { SEED_PHRASE, mockEthereum, web3MockPath } from '../utils'
+import { MISSING_INIT, NO_CONTEXT, NO_PAGE } from './errors'
+
+let context: BrowserContext | undefined
+let cypressPage: Page | undefined
+let keplrWallet: KeplrWallet | undefined
+
+let keplrLoaded = false
+
+const getCypressPage = async () => {
+ if (!context) {
+ console.error(NO_CONTEXT)
+ return
+ }
+
+ cypressPage = context.pages()[0]
+
+ return cypressPage
+}
+
+export async function connectPlaywrightToChrome(port: number) {
+ const debuggerDetails = await fetch(`http://127.0.0.1:${port}/json/version`)
+
+ const debuggerDetailsConfig = (await debuggerDetails.json()) as {
+ webSocketDebuggerUrl: string
+ }
+
+ const browser = await chromium.connectOverCDP(debuggerDetailsConfig.webSocketDebuggerUrl)
+
+ context = browser.contexts()[0]
+
+ return browser.isConnected()
+}
+
+export async function initKeplrWallet(port: number) {
+ await connectPlaywrightToChrome(port)
+
+ if (!context) {
+ console.error(NO_CONTEXT)
+ return
+ }
+
+ await getCypressPage()
+
+ if (!cypressPage) {
+ console.error(NO_PAGE)
+ return
+ }
+
+ await context.addInitScript({
+ content: `${readFileSync(web3MockPath, 'utf-8')}\n(${mockEthereum.toString()})();`
+ })
+
+ // As we want to refresh the page after mocking the ethereum object
+ if (!keplrLoaded) {
+ await cypressPage.reload()
+ keplrLoaded = true
+ }
+
+ keplrWallet = new KeplrWallet(cypressPage)
+ await keplrWallet.setupWallet(SEED_PHRASE, PASSWORD)
+}
+
+export function getKeplrWallet() {
+ if (!context || !cypressPage || !keplrWallet) {
+ console.error(MISSING_INIT)
+ return
+ }
+
+ if (keplrWallet) return keplrWallet
+
+ return new KeplrWallet(cypressPage)
+}
diff --git a/wallets/keplr/src/cypress/installSynpress.ts b/wallets/keplr/src/cypress/installSynpress.ts
new file mode 100644
index 000000000..e805a6017
--- /dev/null
+++ b/wallets/keplr/src/cypress/installSynpress.ts
@@ -0,0 +1,30 @@
+import { ensureRdpPort } from '@synthetixio/synpress-core'
+
+// import { initEthereumWalletMock } from './initEthereumWalletMock'
+// import setupTasks from './setupTasks'
+
+let port: number
+
+export default function installSynpress(on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) {
+ const browsers = config.browsers.filter((b) => b.name === 'chrome')
+ if (browsers.length === 0) {
+ throw new Error('No Chrome browser found in the configuration')
+ }
+
+ on('before:browser:launch', async (_, launchOptions) => {
+ // Enable debug mode to establish playwright connection
+ const args = Array.isArray(launchOptions) ? launchOptions : launchOptions.args
+ port = ensureRdpPort(args)
+ })
+
+ on('before:spec', async () => {
+ await initEthereumWalletMock(port)
+ })
+
+ setupTasks(on)
+
+ return {
+ ...config,
+ browsers
+ }
+}
diff --git a/wallets/keplr/src/cypress/setupTasks.ts b/wallets/keplr/src/cypress/setupTasks.ts
new file mode 100644
index 000000000..6a801b90a
--- /dev/null
+++ b/wallets/keplr/src/cypress/setupTasks.ts
@@ -0,0 +1,27 @@
+import { getEthereumWalletMock } from './initEthereumWalletMock'
+
+export default function setupTasks(on: Cypress.PluginEvents) {
+ on('task', {
+ importWallet: async function (seedPhrase: string) {
+ const ethereumWalletMock = getEthereumWalletMock()
+ if (ethereumWalletMock) {
+ await ethereumWalletMock.importWallet(seedPhrase)
+ }
+ return true
+ },
+ addNewAccount: async function () {
+ const ethereumWalletMock = getEthereumWalletMock()
+ if (ethereumWalletMock) {
+ await ethereumWalletMock.addNewAccount()
+ }
+ return true
+ },
+ getAllAccounts: async function () {
+ const ethereumWalletMock = getEthereumWalletMock()
+ if (ethereumWalletMock) {
+ return await ethereumWalletMock.getAllAccounts()
+ }
+ return []
+ }
+ })
+}
diff --git a/wallets/keplr/src/cypress/support/commands.ts b/wallets/keplr/src/cypress/support/commands.ts
new file mode 100644
index 000000000..3a76ac258
--- /dev/null
+++ b/wallets/keplr/src/cypress/support/commands.ts
@@ -0,0 +1,23 @@
+///
+// ***********************************************
+// This example commands.ts shows you how to
+// create various custom commands and overwrite
+// existing commands.
+//
+// For more comprehensive examples of custom
+// commands please read more here:
+// https://on.cypress.io/custom-commands
+// ***********************************************
+
+import type { WalletMock } from '../../EthereumWalletMock'
+import type { Network } from '../../network/Network'
+
+declare global {
+ namespace Cypress {
+ interface Chainable {
+ setupWallet(secretWordsOnPrivateKeys: string, password: string): Chainable
+ }
+ }
+}
+
+Cypress.Commands.add('setupWallet', (seedPhrase, password) => cy.task('setupWallet', seedPhrase, password))
diff --git a/wallets/keplr/src/cypress/support/e2e.ts b/wallets/keplr/src/cypress/support/e2e.ts
new file mode 100644
index 000000000..c90b6b6d3
--- /dev/null
+++ b/wallets/keplr/src/cypress/support/e2e.ts
@@ -0,0 +1,17 @@
+// ***********************************************************
+// This example support/e2e.ts is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands'