Skip to content

Commit

Permalink
feat: automatic connect to ios app wallet
Browse files Browse the repository at this point in the history
  • Loading branch information
aidanaden committed Sep 23, 2024
1 parent 1691ade commit d8a8243
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 10 deletions.
2 changes: 1 addition & 1 deletion examples/start-tailwind/src/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default function App() {
autoConnect={true}
disconnectOnAccountChange={true}
localStorageKey="unified:wallet-stoarge-key"
env="devnet"
env={"devnet"}
>
<unified-wallet-modal />
<Nav />
Expand Down
2 changes: 1 addition & 1 deletion examples/start-tailwind/src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export default function Home() {
}

// Create an HTTP transport or any custom transport of your choice.
const transport = createDefaultRpcTransport({ url: "https://api.devnet.solana.com" })
const transport = createDefaultRpcTransport({ url: DEVNET_RPC_ENDPOINT })
// Create an RPC client using that transport.
const rpc = createSolanaRpcFromTransport(transport)
const recentBlockhashRes = await rpc.getLatestBlockhash().send()
Expand Down
24 changes: 24 additions & 0 deletions packages/core/src/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,30 @@ export function isSafari(ua: string) {
return ua.includes("safari")
}

/**
* Users on iOS can be redirected into a wallet's in-app browser automatically,
* if that wallet has a universal link configured to do so
* But should not be redirected from within a webview, eg. if they're already
* inside a wallet's browser
* This function can be used to identify users who are on iOS and can be redirected
*
* @returns true if the user can be redirected
*/
export function isIosAndWalletApp() {
// SSR: return false
if (typeof window === "undefined" || !navigator) {
return false
}
const ua = navigator.userAgent.toLowerCase()
// if on iOS the user agent will contain either iPhone or iPad
// caveat: if requesting desktop site then this won't work

// if in a webview then it will not include Safari
// note that other iOS browsers also include Safari
// so we will redirect only if Safari is also included
return isIos(ua) && !isSafari(ua)
}

/**
* Users on iOS can be redirected into a wallet's in-app browser automatically,
* if that wallet has a universal link configured to do so
Expand Down
35 changes: 27 additions & 8 deletions packages/core/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
isWalletAdapterCompatibleStandardWallet,
WalletName,
WalletAdapterCompatibleStandardWallet,
isIosAndRedirectable,
} from "@solana/wallet-adapter-base"
import {
SolanaSignAndSendTransaction,
Expand Down Expand Up @@ -35,8 +34,8 @@ import {
} from "./events"
import { getLocalStorage, KEYS, setLocalStorage } from "./localstorage"
import { THardcodedWalletStandardAdapter } from "./hardcoded-wallet-adapter"
import { isIos } from "./environment"
import { HARDCODED_WALLET_STANDARDS } from "./constants"
import { isIosAndRedirectable, isIosAndWalletApp } from "./environment"

export type Cluster = "devnet" | "testnet" | "mainnet-beta"

Expand Down Expand Up @@ -376,7 +375,16 @@ export function initStore({ env, disconnectOnAccountChange }: StoreProps) {

function getStandardWallets(): WalletAdapterCompatibleStandardWallet[] {
const { get } = getWallets()
return get().filter(w => isWalletAdapterCompatibleStandardWallet(w))
const _wallets = [...get()]
if (isIosAndWalletApp()) {
if ("coinbaseSolana" in window) {
const isCompatible = isWalletAdapterCompatibleStandardWallet(window.coinbaseSolana as any)
alert(`coinbase solana compatible: ${isCompatible}`)
_wallets.push(window.coinbaseSolana as any)
}
}
const available = get().filter(w => isWalletAdapterCompatibleStandardWallet(w))
return available
}

function onMountLoadStandardWallets() {
Expand Down Expand Up @@ -447,12 +455,23 @@ export function initStore({ env, disconnectOnAccountChange }: StoreProps) {
*/
async function onMountAutoConnect() {
const walletName = getLocalStorage<WalletName>(KEYS.WALLET_NAME)
console.log("onMountAutoConnect: ", { walletName })
if (!walletName) {
console.log("onMountAutoConnect: skipping since no previous wallet found")
return
if (walletName) {
await select(walletName)
}
// If IOS and within a wallet app
// we automatically connect to the
// first standard wallet
if (isIosAndWalletApp()) {
const wallets = $wallets.get()
if (wallets.length == 0) {
return
}
const first = $wallets.get()[0]
if (!first) {
return
}
await select(first.wallet.name)
}
await select(walletName)
}

function initOnMount(): (() => void) | undefined {
Expand Down

0 comments on commit d8a8243

Please sign in to comment.