Jerry/emb 296 magic ios feature pairty headless flow#46
Merged
Ethella merged 4 commits intoJun 30, 2026
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR expands the Magic iOS SDK toward feature parity for headless (event-driven) auth flows and adds new platform capabilities (EVM chain switching), while also improving relayer robustness (heartbeat/ping-pong) and key storage behavior.
Changes:
- Add event-driven (PromiEvent-like) auth flow support for Email OTP (emit intermediary events; persistent event subscriptions; error subscriptions).
- Add EVM extension with
switchChain, plus new user methods/config fields (MFA enable/disable,showUIflags). - Improve relayer stability via heartbeat ping/pong and make RPC response handling more robust; adjust keychain item accessibility and synchronizable flags.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Sources/MagicSDK/Utilities/SEKP.swift | Tightens keychain accessibility to ...ThisDeviceOnly and forces non-synchronizable key storage/lookup. |
| Sources/MagicSDK/Modules/Wallet/WalletConfiguration.swift | Minor formatting cleanup. |
| Sources/MagicSDK/Modules/User/UserModule.swift | Updates isLoggedIn method name; adds MFA enable/disable RPC methods. |
| Sources/MagicSDK/Modules/User/UserMethod.swift | Renames/adds RPC method strings (isLoggedIn, MFA, metadata). |
| Sources/MagicSDK/Modules/User/UserConfiguration.swift | Adds showUI to recover account configuration for headless/UI control. |
| Sources/MagicSDK/Modules/EVM/EVMMethod.swift | Introduces EVM RPC method enum. |
| Sources/MagicSDK/Modules/EVM/EVMExtension.swift | Adds public Magic.evm.switchChain module API (Promise + callback). |
| Sources/MagicSDK/Modules/EVM/EVMConfiguration.swift | Adds switch-chain request/response models and EVM network configuration struct. |
| Sources/MagicSDK/Modules/Event/EventPromise.swift | Adds PromiEvent-like API (on, onPersistent, onError, emit, chaining catch) and changes once-subscription naming. |
| Sources/MagicSDK/Modules/Event/EventCenter.swift | Adds support for once vs persistent observers and observer cleanup helper. |
| Sources/MagicSDK/Modules/BaseModule.swift | Adds intermediary-event RPC sender to support headless flows. |
| Sources/MagicSDK/Modules/Auth/AuthModule.swift | Adds event-driven loginWithEmailOTP(showUI:false) overload and new event enum set. |
| Sources/MagicSDK/Modules/Auth/AuthConfiguration.swift | Expands auth configs with showUI, overrides, and lifespan options. |
| Sources/MagicSDK/Core/Relayer/WebViewController.swift | Adds heartbeat ping/pong, improves key window discovery, robust JSON id extraction, and event re-wrapping. |
| Sources/MagicSDK/Core/Relayer/Types/BasicTypes.swift | Adds MAGIC_PING/MAGIC_PONG message types and supports refresh token field on responses. |
| Sources/MagicSDK/Core/Provider/RpcProvider.swift | Stops regenerating request IDs; adds refresh token persistence and attaches rt/jwt to outbound relayer messages. |
| README.md | Updates documentation to point to SwiftUI example app. |
| .swiftpm/xcode/xcshareddata/xcschemes/MagicSDK.xcscheme | Adds shared Xcode scheme. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+141
to
+143
| // Re-wrap as MagicEventResult<[AnyValue]> (non-optional params) so EventCenter cast succeeds | ||
| let result = MagicEventResult<[AnyValue]>(event: eventName, params: event.result.params ?? [], product_announcement: event.result.product_announcement) | ||
| NotificationCenter.default.post(name: Notification.Name.init(eventName), object: nil, userInfo: ["event": result]) |
joshuascan
approved these changes
Jun 30, 2026
Comment on lines
+96
to
+100
| public func logout(response: @escaping Web3ResponseCompletion<Bool>) { | ||
| let request = BasicRPCRequest(method: UserMethod.magic_auth_logout.rawValue, params: []) | ||
| self.provider.send(request: request, response: response) | ||
| self.provider.send(request: request) { [weak self] (result: Web3Response<Bool>) in | ||
| self?.provider.clearRefreshToken() | ||
| response(result) |
Comment on lines
+19
to
24
| /// Subscribe to an inbound event (fires once, then unregisters). | ||
| @discardableResult | ||
| public func on(eventName: String, completion: @escaping () -> Void) -> MagicEventPromise { | ||
| eventCenter.addOnceObserver(eventName: eventName, eventLog: eventLog, completion: completion) | ||
| return self | ||
| } |
Comment on lines
+26
to
+30
| func addOnceObserver(eventName: String, eventLog: Bool, completion: @escaping ([AnyValue]?) -> Void) { | ||
| NotificationCenter.default.addObserver(self, selector: #selector(self.onDidReceiveEvent(_:)), name: Notification.Name(eventName), object: nil) | ||
| self.eventLog = eventLog | ||
| onceHandlerDict[eventName] = completion | ||
| } |
Comment on lines
+36
to
+39
| func addPersistentObserver(eventName: String, eventLog: Bool, completion: @escaping ([AnyValue]?) -> Void) { | ||
| NotificationCenter.default.addObserver(self, selector: #selector(self.onDidReceiveEvent(_:)), name: Notification.Name(eventName), object: nil) | ||
| self.eventLog = eventLog | ||
| eventHandlerDict[eventName] = completion | ||
| persistentHandlerDict[eventName] = completion |
| kSecAttrAccount: account, | ||
| kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked, | ||
| kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly, | ||
| kSecAttrSynchronizable: kCFBooleanFalse!, |
| // Seek a generic password with the given account. | ||
| let query = [kSecClass: kSecClassGenericPassword, | ||
| kSecAttrAccount: account, | ||
| kSecAttrSynchronizable: kCFBooleanFalse!, |
| func deleteKeyFromKeyChain() throws { | ||
| let query = [kSecClass: kSecClassGenericPassword, | ||
| kSecAttrAccount: account, | ||
| kSecAttrSynchronizable: kCFBooleanFalse!, |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.