Skip to content

Commit c0d2931

Browse files
authored
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
1 parent 30124ae commit c0d2931

File tree

7 files changed

+152
-0
lines changed

7 files changed

+152
-0
lines changed

package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@
6262
"import": "./dist/keplr.js",
6363
"require": "./dist/keplr.cjs"
6464
},
65+
"./keplrMobile": {
66+
"types": "./dist/keplrMobile.d.ts",
67+
"import": "./dist/keplrMobile.js",
68+
"require": "./dist/keplrMobile.cjs"
69+
},
6570
"./fordefi": {
6671
"types": "./dist/fordefi.d.ts",
6772
"import": "./dist/fordefi.js",
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export const KEPLR_MOBILE_APP_ICON = `<svg width="32" height="32" viewBox="0 0 128 128" fill="none" xmlns="http://www.w3.org/2000/svg">
2+
<path d="M0 64C0 41.5979 0 30.3969 4.35974 21.8404C8.19467 14.3139 14.3139 8.19467 21.8404 4.35974C30.3969 0 41.5979 0 64 0C86.4021 0 97.6031 0 106.16 4.35974C113.686 8.19467 119.805 14.3139 123.64 21.8404C128 30.3969 128 41.5979 128 64C128 86.4021 128 97.6031 123.64 106.16C119.805 113.686 113.686 119.805 106.16 123.64C97.6031 128 86.4021 128 64 128C41.5979 128 30.3969 128 21.8404 123.64C14.3139 119.805 8.19467 113.686 4.35974 106.16C0 97.6031 0 86.4021 0 64Z" fill="#14AFEB"/>
3+
<path d="M66.6672 41.3438C67.3936 48.7672 67.7565 52.4791 69.7022 55.201C70.5359 56.3673 71.5642 57.3817 72.7418 58.1994C75.4899 60.1076 79.2063 60.4202 86.6387 61.0451L89.7812 61.3091V66.6909L86.6387 66.9549C79.2063 67.5798 75.4899 67.8924 72.7418 69.8006C71.5642 70.6183 70.5359 71.6327 69.7022 72.799C67.7565 75.5209 67.3936 79.2328 66.6672 86.6562H61.3328C60.6064 79.2328 60.2435 75.5209 58.2978 72.799C57.4641 71.6327 56.4358 70.6183 55.2582 69.8006C52.5101 67.8924 48.7937 67.5798 41.3613 66.9549L38.2187 66.6909V61.3091L41.3613 61.0451C48.7937 60.4202 52.5101 60.1076 55.2582 58.1994C56.4358 57.3817 57.4641 56.3673 58.2978 55.201C60.2435 52.4791 60.6064 48.7672 61.3328 41.3438H66.6672Z" fill="white"/>
4+
<path fill-rule="evenodd" clip-rule="evenodd" d="M64 14C105.175 14 114 22.825 114 64C114 105.175 105.175 114 64 114C22.825 114 14 105.175 14 64C14 22.825 22.825 14 64 14ZM96.6782 31.2798C84.5687 19.1705 60.1124 23.9936 42.0533 42.0525C23.9941 60.1117 19.171 84.5687 31.2806 96.6782C43.3902 108.788 67.8464 103.965 85.9055 85.9055C103.965 67.8463 108.788 43.3894 96.6782 31.2798Z" fill="white"/>
5+
</svg>`
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export const isInKeplrMobileAppBrowser = (): boolean => {
2+
if (typeof window === "undefined") {
3+
return false
4+
}
5+
6+
const userAgent = navigator.userAgent
7+
const isKeplrMobileApp = userAgent.includes("KeplrWalletMobile")
8+
9+
if (!isKeplrMobileApp) {
10+
return false
11+
}
12+
13+
return isKeplrMobileApp
14+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./inAppBrowser"
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { type AccountChangeEventHandler } from "@starknet-io/get-starknet-core"
2+
import type {
3+
RequestFnCall,
4+
RpcMessage,
5+
RpcTypeToMessageMap,
6+
StarknetWindowObject,
7+
} from "@starknet-io/types-js"
8+
import type {
9+
AccountInterface,
10+
ProviderInterface,
11+
ProviderOptions,
12+
} from "starknet"
13+
import {
14+
Connector,
15+
type ConnectArgs,
16+
type ConnectorData,
17+
type ConnectorIcons,
18+
} from "../connector"
19+
import { Keplr } from "../injected/keplr"
20+
import { type InjectedConnectorOptions } from "../injected"
21+
import { KEPLR_MOBILE_APP_ICON } from "./constants"
22+
import { isInKeplrMobileAppBrowser } from "./helpers/inAppBrowser"
23+
24+
export class KeplrMobileBaseConnector extends Connector {
25+
private _wallet: StarknetWindowObject | null = null
26+
27+
constructor() {
28+
super()
29+
}
30+
31+
available(): boolean {
32+
return true
33+
}
34+
35+
async ready(): Promise<boolean> {
36+
// return true to be compatible with starknet-react
37+
// will need to be implemented
38+
return true
39+
}
40+
41+
get id(): string {
42+
return "keplrMobile"
43+
}
44+
45+
get name(): string {
46+
return "Keplr (mobile)"
47+
}
48+
49+
get icon(): ConnectorIcons {
50+
return {
51+
dark: KEPLR_MOBILE_APP_ICON,
52+
light: KEPLR_MOBILE_APP_ICON,
53+
}
54+
}
55+
56+
get wallet(): StarknetWindowObject {
57+
throw new Error("not implemented")
58+
}
59+
60+
async connect(_args: ConnectArgs = {}): Promise<ConnectorData> {
61+
await this.ensureWallet()
62+
63+
// will return empty data, connect will only open keplr mobile app
64+
// will require to implement the wallet connection
65+
return {
66+
account: "",
67+
chainId: BigInt(0),
68+
}
69+
}
70+
71+
async disconnect(): Promise<void> {
72+
throw new Error("not implemented")
73+
}
74+
75+
async account(
76+
_: ProviderOptions | ProviderInterface,
77+
): Promise<AccountInterface> {
78+
throw new Error("not implemented")
79+
}
80+
81+
async chainId(): Promise<bigint> {
82+
throw new Error("not implemented")
83+
}
84+
85+
async request<T extends RpcMessage["type"]>(
86+
call: RequestFnCall<T>,
87+
): Promise<RpcTypeToMessageMap[T]["result"]> {
88+
throw new Error("not implemented")
89+
}
90+
91+
// needed, methods required by starknet-react. Otherwise an exception is throwd
92+
async initEventListener(_: AccountChangeEventHandler) {
93+
throw new Error("not implemented")
94+
}
95+
96+
// needed, methods required by starknet-react. Otherwise an exception is throwd
97+
async removeEventListener(_: AccountChangeEventHandler) {
98+
throw new Error("not implemented")
99+
}
100+
101+
private async ensureWallet(): Promise<void> {
102+
window.open(
103+
`https://deeplink.keplr.app/web-browser?url=${encodeURIComponent(window.origin)}`,
104+
"_blank",
105+
)
106+
}
107+
}
108+
109+
export interface KeplrMobileConnectorInitParams {
110+
inAppBrowserOptions?: Omit<InjectedConnectorOptions, "id">
111+
}
112+
113+
export class KeplrMobileConnector {
114+
static init(params?: KeplrMobileConnectorInitParams): Connector {
115+
const { inAppBrowserOptions } = params || {}
116+
if (isInKeplrMobileAppBrowser()) {
117+
return new Keplr(inAppBrowserOptions)
118+
} else {
119+
return new KeplrMobileBaseConnector()
120+
}
121+
}
122+
}
123+
124+
export { isInKeplrMobileAppBrowser }

src/helpers/defaultConnectors.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { StarknetkitConnector } from "../connectors"
22
import { type ArgentMobileConnectorOptions } from "../connectors/argent/argentMobile"
33
import { BraavosMobileBaseConnector } from "../connectors/braavosMobile"
4+
import { KeplrMobileBaseConnector } from "../connectors/keplrMobile"
45
import { ControllerConnector } from "../connectors/controller"
56
import { WebWalletConnector } from "../connectors/webwallet"
67
import { Braavos } from "../connectors/injected/braavos"
@@ -43,6 +44,7 @@ export const defaultConnectors = ({
4344

4445
if (isMobileDevice()) {
4546
defaultConnectors.push(new BraavosMobileBaseConnector())
47+
defaultConnectors.push(new KeplrMobileBaseConnector())
4648
}
4749

4850
return defaultConnectors

vite.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default defineConfig({
2727
__dirname,
2828
"src/connectors/webwallet/index.ts",
2929
),
30+
keplrMobile: resolve(__dirname, "src/connectors/keplrMobile/index.ts"),
3031
argentMobile: resolve(
3132
__dirname,
3233
"src/connectors/argent/argentMobile/index.ts",

0 commit comments

Comments
 (0)