From c0d2931ca157cfd782d54d3afe68bedbab4ed5be Mon Sep 17 00:00:00 2001
From: Sam <60031762+kws1207@users.noreply.github.com>
Date: Tue, 30 Sep 2025 22:42:01 +0900
Subject: [PATCH] feat: Add Keplr mobile connector (#1)
* feat: Add Keplr mobile connector
* feat: Add keplr mobile to package.json exports and vite config
* fix: Use user agent for isInKeplrMobileAppBrowser
* fix: Add _wallet to KeplrMobileBaseConnector
* feat: Add KeplrMobileBaseConnector to defaultConnectors
---
package.json | 5 +
src/connectors/keplrMobile/constants.ts | 5 +
.../keplrMobile/helpers/inAppBrowser.ts | 14 ++
src/connectors/keplrMobile/helpers/index.ts | 1 +
src/connectors/keplrMobile/index.ts | 124 ++++++++++++++++++
src/helpers/defaultConnectors.ts | 2 +
vite.config.ts | 1 +
7 files changed, 152 insertions(+)
create mode 100644 src/connectors/keplrMobile/constants.ts
create mode 100644 src/connectors/keplrMobile/helpers/inAppBrowser.ts
create mode 100644 src/connectors/keplrMobile/helpers/index.ts
create mode 100644 src/connectors/keplrMobile/index.ts
diff --git a/package.json b/package.json
index e0555385..223ca80c 100644
--- a/package.json
+++ b/package.json
@@ -62,6 +62,11 @@
"import": "./dist/keplr.js",
"require": "./dist/keplr.cjs"
},
+ "./keplrMobile": {
+ "types": "./dist/keplrMobile.d.ts",
+ "import": "./dist/keplrMobile.js",
+ "require": "./dist/keplrMobile.cjs"
+ },
"./fordefi": {
"types": "./dist/fordefi.d.ts",
"import": "./dist/fordefi.js",
diff --git a/src/connectors/keplrMobile/constants.ts b/src/connectors/keplrMobile/constants.ts
new file mode 100644
index 00000000..ef85ab91
--- /dev/null
+++ b/src/connectors/keplrMobile/constants.ts
@@ -0,0 +1,5 @@
+export const KEPLR_MOBILE_APP_ICON = ``
diff --git a/src/connectors/keplrMobile/helpers/inAppBrowser.ts b/src/connectors/keplrMobile/helpers/inAppBrowser.ts
new file mode 100644
index 00000000..856534fe
--- /dev/null
+++ b/src/connectors/keplrMobile/helpers/inAppBrowser.ts
@@ -0,0 +1,14 @@
+export const isInKeplrMobileAppBrowser = (): boolean => {
+ if (typeof window === "undefined") {
+ return false
+ }
+
+ const userAgent = navigator.userAgent
+ const isKeplrMobileApp = userAgent.includes("KeplrWalletMobile")
+
+ if (!isKeplrMobileApp) {
+ return false
+ }
+
+ return isKeplrMobileApp
+}
diff --git a/src/connectors/keplrMobile/helpers/index.ts b/src/connectors/keplrMobile/helpers/index.ts
new file mode 100644
index 00000000..bfe3f220
--- /dev/null
+++ b/src/connectors/keplrMobile/helpers/index.ts
@@ -0,0 +1 @@
+export * from "./inAppBrowser"
diff --git a/src/connectors/keplrMobile/index.ts b/src/connectors/keplrMobile/index.ts
new file mode 100644
index 00000000..b96891eb
--- /dev/null
+++ b/src/connectors/keplrMobile/index.ts
@@ -0,0 +1,124 @@
+import { type AccountChangeEventHandler } from "@starknet-io/get-starknet-core"
+import type {
+ RequestFnCall,
+ RpcMessage,
+ RpcTypeToMessageMap,
+ StarknetWindowObject,
+} from "@starknet-io/types-js"
+import type {
+ AccountInterface,
+ ProviderInterface,
+ ProviderOptions,
+} from "starknet"
+import {
+ Connector,
+ type ConnectArgs,
+ type ConnectorData,
+ type ConnectorIcons,
+} from "../connector"
+import { Keplr } from "../injected/keplr"
+import { type InjectedConnectorOptions } from "../injected"
+import { KEPLR_MOBILE_APP_ICON } from "./constants"
+import { isInKeplrMobileAppBrowser } from "./helpers/inAppBrowser"
+
+export class KeplrMobileBaseConnector extends Connector {
+ private _wallet: StarknetWindowObject | null = null
+
+ constructor() {
+ super()
+ }
+
+ available(): boolean {
+ return true
+ }
+
+ async ready(): Promise {
+ // return true to be compatible with starknet-react
+ // will need to be implemented
+ return true
+ }
+
+ get id(): string {
+ return "keplrMobile"
+ }
+
+ get name(): string {
+ return "Keplr (mobile)"
+ }
+
+ get icon(): ConnectorIcons {
+ return {
+ dark: KEPLR_MOBILE_APP_ICON,
+ light: KEPLR_MOBILE_APP_ICON,
+ }
+ }
+
+ get wallet(): StarknetWindowObject {
+ throw new Error("not implemented")
+ }
+
+ async connect(_args: ConnectArgs = {}): Promise {
+ await this.ensureWallet()
+
+ // will return empty data, connect will only open keplr mobile app
+ // will require to implement the wallet connection
+ return {
+ account: "",
+ chainId: BigInt(0),
+ }
+ }
+
+ async disconnect(): Promise {
+ throw new Error("not implemented")
+ }
+
+ async account(
+ _: ProviderOptions | ProviderInterface,
+ ): Promise {
+ throw new Error("not implemented")
+ }
+
+ async chainId(): Promise {
+ throw new Error("not implemented")
+ }
+
+ async request(
+ call: RequestFnCall,
+ ): Promise {
+ throw new Error("not implemented")
+ }
+
+ // needed, methods required by starknet-react. Otherwise an exception is throwd
+ async initEventListener(_: AccountChangeEventHandler) {
+ throw new Error("not implemented")
+ }
+
+ // needed, methods required by starknet-react. Otherwise an exception is throwd
+ async removeEventListener(_: AccountChangeEventHandler) {
+ throw new Error("not implemented")
+ }
+
+ private async ensureWallet(): Promise {
+ window.open(
+ `https://deeplink.keplr.app/web-browser?url=${encodeURIComponent(window.origin)}`,
+ "_blank",
+ )
+ }
+}
+
+export interface KeplrMobileConnectorInitParams {
+ inAppBrowserOptions?: Omit
+}
+
+export class KeplrMobileConnector {
+ static init(params?: KeplrMobileConnectorInitParams): Connector {
+ const { inAppBrowserOptions } = params || {}
+ if (isInKeplrMobileAppBrowser()) {
+ return new Keplr(inAppBrowserOptions)
+ } else {
+ return new KeplrMobileBaseConnector()
+ }
+ }
+}
+
+export { isInKeplrMobileAppBrowser }
diff --git a/src/helpers/defaultConnectors.ts b/src/helpers/defaultConnectors.ts
index dee8e3e6..016dae81 100644
--- a/src/helpers/defaultConnectors.ts
+++ b/src/helpers/defaultConnectors.ts
@@ -1,6 +1,7 @@
import type { StarknetkitConnector } from "../connectors"
import { type ArgentMobileConnectorOptions } from "../connectors/argent/argentMobile"
import { BraavosMobileBaseConnector } from "../connectors/braavosMobile"
+import { KeplrMobileBaseConnector } from "../connectors/keplrMobile"
import { ControllerConnector } from "../connectors/controller"
import { WebWalletConnector } from "../connectors/webwallet"
import { Braavos } from "../connectors/injected/braavos"
@@ -43,6 +44,7 @@ export const defaultConnectors = ({
if (isMobileDevice()) {
defaultConnectors.push(new BraavosMobileBaseConnector())
+ defaultConnectors.push(new KeplrMobileBaseConnector())
}
return defaultConnectors
diff --git a/vite.config.ts b/vite.config.ts
index e16c4300..41e74fb8 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -27,6 +27,7 @@ export default defineConfig({
__dirname,
"src/connectors/webwallet/index.ts",
),
+ keplrMobile: resolve(__dirname, "src/connectors/keplrMobile/index.ts"),
argentMobile: resolve(
__dirname,
"src/connectors/argent/argentMobile/index.ts",