Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Radix Connect for Mobile #1157

Merged
merged 132 commits into from
Jun 28, 2024
Merged

Radix Connect for Mobile #1157

merged 132 commits into from
Jun 28, 2024

Conversation

GhenadieVP
Copy link
Contributor

@GhenadieVP GhenadieVP commented Jun 3, 2024

Radix Connect for Mobile implementation.

This PR is the Wallet integration of Sargon's RadixConnectMobile API - radixdlt/sargon#122. All of the RCfM logic is in Sargon, while Wallet is responsible for intercepting the DeepLink and present the request to the user.

What has been done

  • Added the simple DeepLink setup that allows the Wallet to receive deep link requests.
  • Integrated Sargon's RadixConnectMobile which responsible for parsing the deep link request, establish the session and send back the response.
  • Integrated the RadixConnectMobile into RadixConnect client, so the requests received over deepLink are then propagated in the app the same way as requests from WebRTC or from within the Wallet.
  • Added the new deepLink route, so the Wallet acts accordingly depending when this route is involved.
  • Add the origin verification screen, as well a generic way of showing it if a request does not have the origin pre-verified.

Demo

https://drive.google.com/file/d/1REicQe4gyIXMAKoifMS2pERMuYmrNsQr/view?usp=sharing&t=73.

@GhenadieVP GhenadieVP changed the title Draft: RCfM Radix Connect for Mobile Jun 24, 2024
@@ -109,15 +109,6 @@
"version" : "11.6.4"
}
},
{
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will be replaced with Sargon version once the related PR is merged in Sargon

Copy link
Contributor

@danvleju-rdx danvleju-rdx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good!
Left some minor comments.
Will do more testing after Sargon PR merge.

Copy link
Contributor

@matiasbzurovski matiasbzurovski left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking very clean!

}

extension DeepLinkHandlerClient {
public typealias HandleDeepLink = () -> Void
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Sendable on all function types?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed, as those functions are only called from the main thread.

// MARK: - DeepLinkHandlerClient
/// A client that manages the handling of the received deepLink.
/// It will delegate the deepLink to the respective subcomponent.
public struct DeepLinkHandlerClient: DependencyKey {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm should client be Sendable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not needed, it is used only from the main thread really. I could add it for the sake of it, but it will not be useful.

var bufferedDeepLink: URL?
}

var state = State()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Im unsure if this passes complete Isolation check? Since state is references referenced/mutated from multiple closures.

Might be solved with @TaskLocal?

Copy link
Contributor Author

@GhenadieVP GhenadieVP Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but all of the closures are not executed in a concurrent context, there will not be two concurrent deepLinks to be handled at the same time.

extension DeepLinkHandlerClient: TestDependencyKey {
public static let previewValue = Self.noop

public static let testValue = Self(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is not needed any more, if you use @DependencyClient macro on DeepLinkHandlerClient.

func loadSession(sessionId: SessionId) async throws -> Data? {
try secureStorageClient.loadRadixConnectMobileSession(sessionId)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps a small unit tests for this? Just calling save and then load and assert the correct session data is loaded?

/// A very thin wrapper around Sargon.RadixConnectMobile.
/// It mainly initializes the `live` version Sargon.RadixConnectMobile and
/// exposes the incomming messages stream.
struct RadixConnectMobile {
Copy link
Contributor

@Sajjon Sajjon Jun 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess P2P.RTCIncomingMessage does not exist in Sargon? preventing this struct to be implemented in Swift Sargon?

What if you make this struct generic?

// This will be `Sargon.RadixConnectMobile` (vs `SargonUniFFI.RadixConnectMobile`)
public struct RadixConnectMobile<Storage, Message> where Storage: SessionStorage {
   private let radixConnectMobile: SargonUniFFI.RadixConnectMobile // N.B. `SargonUniFFI.`
   ... incomingMessagesSubject: AsyncReplaySubject<Message> ...

   public init(storage: Storage) {
       self.radixConnectMobile = SargonUniFFI.RadixConnectMobile.live(sessionStorage: storage)

   }
}

extension RadixConnectMobile {
    func incomingMessages() async -> AnyAsyncSequence<Message> {
		...
	}
}

Then it can be placed in Swift Sargon, with all the benefits that entails:

  • Easy to write unit tests
  • Getting code coverage measurements

Copy link
Contributor Author

@GhenadieVP GhenadieVP Jun 27, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't quite follow your suggestion, why I would make this generic when it is specific to RadixConnectMobile.

P2P.RTCIncomingMessage does not exist in Sargon, since it does not yet know about messages from WebRTC or from the Wallet itself; also it is highly specific to iOS.

Copy link
Contributor

@Sajjon Sajjon Jun 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2P.RTCIncomingMessage does not exist in Sargon,

that is my point, P2P.RTCIncomingMessage does not exist in Sargon. But a generic type T can be declared ("exist") in Sargon. Thus this struct RadixConnectMobile<T> can exist in Sargon. Which works, since this type does not actually create any T or read any fields of T. And having Swift code In Sargon has the above mentioned two advantages:

  • Easy to write unit tests
  • Getting code coverage measurements

VS the terrible DX of writing unit tests in iOS app repo - without code coverage.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, we can get to this at some later point when we can unify the channel of incoming message on both platforms.

Copy link
Contributor

@CyonAlexRDX CyonAlexRDX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sweet! LGTM

@GhenadieVP GhenadieVP merged commit a167a1b into main Jun 28, 2024
6 checks passed
@GhenadieVP GhenadieVP deleted the deep_linking branch June 28, 2024 08:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

6 participants