diff --git a/packages/core/src/discovery.ts b/packages/core/src/discovery.ts index 8c08a58d..f7faf301 100644 --- a/packages/core/src/discovery.ts +++ b/packages/core/src/discovery.ts @@ -1,12 +1,36 @@ +import { ssrSafeWindow } from "./utils" + +export type OperatingSystemStoreVersion = "ios" | "android" +export type BrowserStoreVersion = "chrome" | "firefox" | "edge" | "safari" + +type DownloadsRecord< + SV extends OperatingSystemStoreVersion | BrowserStoreVersion, + DL extends string, +> = Record + export type WalletProvider = { id: string name: string icon: string downloads: - | { chrome?: `https://chrome.google.com/webstore/detail/${string}` } - | { firefox?: `https://addons.mozilla.org/en-US/firefox/addon/${string}` } - | { edge?: `https://microsoftedge.microsoft.com/addons/detail/${string}` } - | { safari?: `https://apps.apple.com/us/app/${string}` } + | DownloadsRecord< + "chrome", + `https://chrome.google.com/webstore/detail/${string}` + > + | DownloadsRecord< + "firefox", + `https://addons.mozilla.org/en-US/firefox/addon/${string}` + > + | DownloadsRecord< + "edge", + `https://microsoftedge.microsoft.com/addons/detail/${string}` + > + | DownloadsRecord<"safari", `https://apps.apple.com/us/app/${string}`> + | DownloadsRecord<"ios", `https://apps.apple.com/us/app/${string}`> + | DownloadsRecord< + "android", + `https://play.google.com/store/apps/details?id=${string}` + > } const wallets: WalletProvider[] = [ @@ -30,7 +54,9 @@ const wallets: WalletProvider[] = [ "https://chrome.google.com/webstore/detail/braavos-wallet/jnlgamecbpmbajjfhmmmlhejkemejdma", firefox: "https://addons.mozilla.org/en-US/firefox/addon/braavos-wallet", edge: "https://microsoftedge.microsoft.com/addons/detail/braavos-wallet/hkkpjehhcnhgefhbdcgfkeegglpjchdc", - }, + ios: `https://link.braavos.app/dapp/${ssrSafeWindow?.location?.host}`, + android: `https://link.braavos.app/dapp/${ssrSafeWindow?.location?.host}`, + } as Record, }, { id: "okxwallet", diff --git a/packages/core/src/main.ts b/packages/core/src/main.ts index 245a96ed..a1438990 100644 --- a/packages/core/src/main.ts +++ b/packages/core/src/main.ts @@ -4,7 +4,7 @@ import { } from "./StarknetWindowObject" import discovery, { WalletProvider } from "./discovery" import { IStorageWrapper, LocalStorageWrapper } from "./localStorageStore" -import { pipe } from "./utils" +import { pipe, ssrSafeWindow } from "./utils" import { FilterList, filterBy, filterByPreAuthorized } from "./wallet/filter" import { isWalletObj } from "./wallet/isWalletObject" import { injectMetamaskBridge } from "./wallet/metamaskBridge" @@ -24,7 +24,11 @@ export type { DisconnectedStarknetWindowObject, IStarknetWindowObject, } from "./StarknetWindowObject" -export type { WalletProvider } from "./discovery" +export type { + WalletProvider, + BrowserStoreVersion, + OperatingSystemStoreVersion, +} from "./discovery" export interface GetStarknetOptions { windowObject: Record @@ -32,10 +36,8 @@ export interface GetStarknetOptions { storageFactoryImplementation: (name: string) => IStorageWrapper } -const ssrSafeWindow = typeof window !== "undefined" ? window : {} - const defaultOptions: GetStarknetOptions = { - windowObject: ssrSafeWindow, + windowObject: ssrSafeWindow ?? {}, isWalletObject: isWalletObj, storageFactoryImplementation: (name: string) => new LocalStorageWrapper(name), } @@ -139,4 +141,6 @@ export function getStarknet( } } +export { ssrSafeWindow } from "./utils" + export default getStarknet() diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts index e4555dd2..b9dd8e81 100644 --- a/packages/core/src/utils.ts +++ b/packages/core/src/utils.ts @@ -18,3 +18,6 @@ export function pipe( ): (arg: T) => Promise { return (arg: T) => fns.reduce((acc, fn) => acc.then(fn), Promise.resolve(arg)) } + +export const ssrSafeWindow: Window | null = + typeof window !== "undefined" ? window : null diff --git a/packages/ui/src/main.ts b/packages/ui/src/main.ts index 34eec3eb..b6d13be4 100644 --- a/packages/ui/src/main.ts +++ b/packages/ui/src/main.ts @@ -1,18 +1,18 @@ import show, { type WalletProviderWithStoreVersion } from "./modal" import Bowser from "bowser" import sn, { + type BrowserStoreVersion, type DisconnectOptions, type GetWalletOptions, + type OperatingSystemStoreVersion, type StarknetWindowObject, + type WalletProvider, + ssrSafeWindow, } from "get-starknet-core" export type { StarknetWindowObject, DisconnectOptions } from "get-starknet-core" -type StoreVersion = "chrome" | "firefox" | "edge" | "safari" - -const ssrSafeWindow = typeof window !== "undefined" ? window : null - -function getStoreVersionFromBrowser(): StoreVersion | null { +function getBrowserStoreVersionFromBrowser(): BrowserStoreVersion | null { const browserName = Bowser.getParser(ssrSafeWindow?.navigator.userAgent) .getBrowserName() ?.toLowerCase() @@ -35,10 +35,25 @@ function getStoreVersionFromBrowser(): StoreVersion | null { } } +function getOperatingSystemStoreVersionFromBrowser(): OperatingSystemStoreVersion | null { + const os = + Bowser.getParser(ssrSafeWindow?.navigator.userAgent) + .getOS() + ?.name?.toLowerCase() ?? null + switch (os) { + case "ios": + case "android": + return os + default: + return null + } +} + export interface ConnectOptions extends GetWalletOptions { modalMode?: "alwaysAsk" | "canAsk" | "neverAsk" modalTheme?: "light" | "dark" | "system" - storeVersion?: StoreVersion + storeVersion?: BrowserStoreVersion + osVersion?: OperatingSystemStoreVersion } const enableWithVersion = async (wallet: StarknetWindowObject | null) => { @@ -50,7 +65,8 @@ const enableWithVersion = async (wallet: StarknetWindowObject | null) => { export const connect = async ({ modalMode = "canAsk", - storeVersion = getStoreVersionFromBrowser(), + storeVersion = getBrowserStoreVersionFromBrowser(), + osVersion = getOperatingSystemStoreVersionFromBrowser(), modalTheme, ...restOptions }: ConnectOptions = {}): Promise => { @@ -85,13 +101,26 @@ export const connect = async ({ const discoveryWallets = await sn.getDiscoveryWallets(restOptions) - const discoveryWalletsByStoreVersion: WalletProviderWithStoreVersion[] = - discoveryWallets - .filter((w) => Boolean(w.downloads[storeVersion])) - .map(({ downloads, ...w }) => ({ - ...w, - download: downloads[storeVersion], - })) + const discoveryWalletsByStoreVersion = discoveryWallets.reduce< + WalletProviderWithStoreVersion[] + >((results, w) => { + const download = + // prioritize OS url + w.downloads[osVersion] || + // fallback to browser url + w.downloads[storeVersion] + if (download) { + const store = Object.keys(w.downloads).find( + (key) => w.downloads[key] === download, + ) as keyof WalletProvider["downloads"] + + const isMobileStore = store === "android" || store === "ios" + const name = isMobileStore ? `${w.name} Mobile` : `Install ${w.name}` + + results.push({ ...w, name, download }) + } + return results + }, []) return show({ lastWallet, diff --git a/packages/ui/src/modal/Modal.svelte b/packages/ui/src/modal/Modal.svelte index ed185845..1ad7baae 100644 --- a/packages/ui/src/modal/Modal.svelte +++ b/packages/ui/src/modal/Modal.svelte @@ -143,7 +143,7 @@ cb(null) } }}> - Install {discoveryWallet.name} + {discoveryWallet.name}