Safari Web Extension Wallet for iOS
This repository showcases an example iOS wallet that utilizes a Safari Web Extension to enable wallet signing within the Safari browser. This is a proof of concept and its implementation of key storage is unencrypted and should not be replicated in a real wallet.
Demo
Video of a Jupiter Exchange swap
Installation
- Download Xcode
- Build the Extension’s JS bundle:
cd js-extension && npm install && npm run build:publish
- Follow the “Enable App Groups” steps below.
- Open the project in Xcode, choose your simulator/device, build and run.
Enable App Groups
In order for the Safari Extension to read the same UserDefaults
or Keychain as the iOS app, they need to use a shared App group.
- In Xcode, select the project > Signing & Capabilities > App Groups
- At the bottom, add an App Group identifier.
- In
/Shared/KeypairUtil.swift
, edit thesharedUserDefaults()
function to use your app group identifier.
func sharedUserDefaults() -> UserDefaults? {
return UserDefaults(suiteName: "group.your.app")
}
Now your native app and extension handler can read and write to the same UserDefaults!
Enable the extension
- In Safari, press the Aa menu and click Manage Extensions
- In the extensions list, find the name, “Solana Safari Extension Wallet”, and enable it.
- Back in the Aa menu, press new “Solana Safari Extension Wallet” button.
- Select “Always allow” then “Always allow on every website”.
Folder Reference
js-extension
: The React UI that renders within the safari browser. The UI is bundled into raw minified .js
scripts which are exported to the Safari Extension folder with npm run build:publish
.
SolanaSafariWalletExtension Extension
: The Safari Web Extension Swift code. TThis contains the bundled js
and html
from the js-extension
folder and also the Extension handler code, which acts as a bridge between JS and the native app.
SolanaSafariWalletExtension
: The native iOS wallet app built with SwiftUI.
What is a Safari Web Extension?
A Safari Web Extension allows an iOS app to add customized functionality to the Safari mobile browser. Similar to a Chrome browser extension, the Safari Web Extension can run background/content scripts and inject javascript into the web page.
The key benefit of the web extension on mobile is that it is able to securely communicate with the native iOS app and relay information to the web page.
Wallet Standard
Just like Chrome extension wallets, this uses Wallet-standard to subscribe and respond to requests from the dApp. It is automatically compatible with existing Solana web dApps.
Example: Connect Request Flow
-
On page load, the JS extension injects a page script (
injected.ts
) that registers the wallet implementation towindow
using Wallet-standard’sregisterWallet
. -
When a standard Connect event is emitted, the wallet provider (
provider.ts
) relays it to the Extension’s content script (content.ts
) withwindow.postMessage
. -
The content script forwards this message to the Extension’s background script (
background.ts
) usingbrowser.runtime.sendMessage
. -
The background script initializes the Approval UI Tab (
approval.tsx
) usingbrowser.tabs
API. -
On approve, the Approval UI tab sends the connect response back to the connecting dApp (
browser.tabs.sendMessage(originTabId, response)
).