Fix: WalletConnect mobile linking (i.e when using WalletConnect from iOS Safari, switching to the app with a deeplink) broken

pull/3378/head
Hwee-Boon Yar 3 years ago
parent 508262ec81
commit 6c62708def
  1. 4
      AlphaWallet.xcodeproj/project.pbxproj
  2. 10
      AlphaWallet/Core/Helpers/RemoteLogger.swift
  3. 38
      AlphaWallet/Market/Coordinators/UniversalLinkCoordinator.swift
  4. 16
      AlphaWalletTests/Market/UniversalLinkCoordinatorTests.swift

@ -475,6 +475,7 @@
5E7C793F7E346402CDAF771F /* AssetDefinitionStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7FE30D58E4022AF04E48 /* AssetDefinitionStoreTests.swift */; };
5E7C797BE2C8DB7EF6F217B3 /* OnboardingPage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7103135DCCCAB96EE5FC /* OnboardingPage.swift */; };
5E7C797F3278A290BE47BFA2 /* TokenIdOrEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C78302634885C93D9B6FA /* TokenIdOrEvent.swift */; };
5E7C79880D398BF8D145D666 /* UniversalLinkCoordinatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C74A5A91E5DE208B33325 /* UniversalLinkCoordinatorTests.swift */; };
5E7C798A5D213DD92F24CBFB /* AssetImplicitAttributes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C78FAB9070B10A476DB29 /* AssetImplicitAttributes.swift */; };
5E7C799DED280839CE80FCD3 /* URLTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C7DCF28B3F0342113E20E /* URLTests.swift */; };
5E7C79BFFFB6A5FE833489C0 /* ActivitiesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5E7C72E648B7C34EDA193BDA /* ActivitiesCoordinator.swift */; };
@ -1345,6 +1346,7 @@
5E7C74822F5F71748184F6C1 /* EventInstance.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EventInstance.swift; sourceTree = "<group>"; };
5E7C7487BDF72352446E1266 /* ImportTokenViewControllerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImportTokenViewControllerTests.swift; sourceTree = "<group>"; };
5E7C74A1A13A1A6CB9E61BAC /* TokenListFormatRowViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TokenListFormatRowViewModel.swift; sourceTree = "<group>"; };
5E7C74A5A91E5DE208B33325 /* UniversalLinkCoordinatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UniversalLinkCoordinatorTests.swift; sourceTree = "<group>"; };
5E7C74A5B5B9D8AD0BD913C1 /* CreateInitialWalletViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateInitialWalletViewController.swift; sourceTree = "<group>"; };
5E7C74B424FB5DE3A4D6A2F4 /* DappsHomeEmptyViewViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DappsHomeEmptyViewViewModel.swift; sourceTree = "<group>"; };
5E7C74B82783A94091A43470 /* EthTokenViewCellViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EthTokenViewCellViewModel.swift; sourceTree = "<group>"; };
@ -4166,6 +4168,7 @@
76F1DE8ADA3176D0277EDF20 /* OrderSigningTests.swift */,
76F1D96298E216CBFC3DD78B /* UniversalLinkHandlerTests.swift */,
5E7C77C33FD8D5653F051136 /* ViewControllers */,
5E7C74A5A91E5DE208B33325 /* UniversalLinkCoordinatorTests.swift */,
);
path = Market;
sourceTree = "<group>";
@ -6275,6 +6278,7 @@
5E7C799DED280839CE80FCD3 /* URLTests.swift in Sources */,
5E7C7A7FFA16D3505F94BB9E /* FakeActivitiesService.swift in Sources */,
5E7C775BE0C1CF2B2FCAEA4B /* DecodedFunctionCall+DecodeTests.swift in Sources */,
5E7C79880D398BF8D145D666 /* UniversalLinkCoordinatorTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

@ -99,22 +99,22 @@ final class DDLogger: Logger {
}
func debug(_ message: Any) {
DDLogDebug(message, ddlog: logger)
DDLogDebug("xxx \(message)", ddlog: logger)
}
func info(_ message: Any) {
DDLogInfo(message, ddlog: logger)
DDLogInfo("xxx \(message)", ddlog: logger)
}
func warn(_ message: Any) {
DDLogWarn(message, ddlog: logger)
DDLogWarn("xxx \(message)", ddlog: logger)
}
func verbose(_ message: Any) {
DDLogVerbose(message, ddlog: logger)
DDLogVerbose("xxx \(message)", ddlog: logger)
}
func error(_ message: Any) {
DDLogError(message, ddlog: logger)
DDLogError("xxx \(message)", ddlog: logger)
}
}

@ -26,7 +26,7 @@ enum MagicLinkURL {
init?(url: URL) {
if let eip681Url = Self.hasEip681Path(in: url) {
self = .eip681(eip681Url)
} else if let wcUrl = Self.hasWalletConnectPath(in: url) {
} else if let wcUrl = Self.functional.hasWalletConnectPath(in: url) {
self = .walletConnect(wcUrl)
} else {
return nil
@ -46,13 +46,43 @@ enum MagicLinkURL {
return nil
}
}
}
extension MagicLinkURL {
class functional {}
}
//E.g. https://aw.app/wc:f607884e-63a5-4fa3-8e7d-af6f6fa9b51f@1?bridge=https%3A%2F%2Fn.bridge.walletconnect.org&key=cff9abba23cb9f843e9d623b891a5f8948b41f7d4afc7f7155aa252504cd8264
private static func hasWalletConnectPath(in url: URL) -> WalletConnectURL? {
guard let magicLink = RPCServer(withMagicLink: url), url.path.starts(with: Self.walletConnectPath) else { return nil }
extension MagicLinkURL.functional {
//Multiple formats:
//From WalletConnect mobile linking: e.g. https://aw.app/wc?uri=wc%3A588422fd-929d-438a-b337-31c3c9184d9b%401%3Fbridge%3Dhttps%253A%252F%252Fbridge.walletconnect.org%26key%3D8f9459f72aed0790282c47fe45f37ed5cb121bc17795f8f2a229a910bc447202
//From AlphaWallet iOS Safari extension's rewriting: eg. https://aw.app/wc:f607884e-63a5-4fa3-8e7d-af6f6fa9b51f@1?bridge=https%3A%2F%2Fn.bridge.walletconnect.org&key=cff9abba23cb9f843e9d623b891a5f8948b41f7d4afc7f7155aa252504cd8264
static func hasWalletConnectPath(in url: URL) -> WalletConnectURL? {
guard url.path.starts(with: MagicLinkURL.walletConnectPath) else { return nil }
if let url = extractWalletConnectUrlFromSafariExtensionRewrittenUrl(url) {
return url
} else if let url = extractWalletConnectUrlFromWalletConnectMobileLinking(url) {
return url
} else {
return nil
}
}
private static func extractWalletConnectUrlFromSafariExtensionRewrittenUrl(_ url: URL) -> WalletConnectURL? {
guard let magicLink = RPCServer(withMagicLink: url) else { return nil }
let wcUrl = url.absoluteString.replacingOccurrences(of: magicLink.magicLinkPrefix.absoluteString, with: "")
return WalletConnectURL(wcUrl)
}
private static func extractWalletConnectUrlFromWalletConnectMobileLinking(_ url: URL) -> WalletConnectURL? {
guard let queryItems = URLComponents(url: url, resolvingAgainstBaseURL: true)?.queryItems else { return nil }
guard let string = queryItems.first(where: { $0.name == "uri" })?.value else { return nil }
if let walletConnectUrl = WalletConnectURL(string) {
return walletConnectUrl
} else {
//no-op. According to WalletConnect docs, this is just to get iOS to switch over to the app for signing, etc. e.g. https://aw.app/wc?uri=wc:00e46b69-d0cc-4b3e-b6a2-cee442f97188@1
return nil
}
}
}
// swiftlint:disable type_body_length

@ -0,0 +1,16 @@
// Copyright © 2021 Stormbird PTE. LTD.
@testable import AlphaWallet
import XCTest
class UniversalLinkCoordinatorTests: XCTestCase {
func testHasWalletConnectPathFromSafariExtensionRewriting() {
let url = URL(string: "https://aw.app/wc:f607884e-63a5-4fa3-8e7d-af6f6fa9b51f@1?bridge=https%3A%2F%2Fn.bridge.walletconnect.org&key=cff9abba23cb9f843e9d623b891a5f8948b41f7d4afc7f7155aa252504cd8264")!
XCTAssertNotNil(MagicLinkURL.functional.hasWalletConnectPath(in: url))
}
func testHasWalletConnectPathFromMobileLinking() {
let url = URL(string: "https://aw.app/wc?uri=wc%3A588422fd-929d-438a-b337-31c3c9184d9b%401%3Fbridge%3Dhttps%253A%252F%252Fbridge.walletconnect.org%26key%3D8f9459f72aed0790282c47fe45f37ed5cb121bc17795f8f2a229a910bc447202")!
XCTAssertNotNil(MagicLinkURL.functional.hasWalletConnectPath(in: url))
}
}
Loading…
Cancel
Save