-
Notifications
You must be signed in to change notification settings - Fork 9
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
[ABW-1315] Radix Connect requset to CE and response from CE #444
Changes from all commits
97de727
49ebef1
d7664fc
8ef1731
a2ffa8a
8486383
2fe081e
a3c1652
2cf68db
3fcbc6d
d237d94
ee4d5c0
2eb65e9
11fe2dc
7d2ec7f
293d7a1
c06ee8d
678cde9
42c900e
2b41bdb
441f4f9
a8ba2a6
6be08b1
a506908
4c6ad75
9531911
58347b2
bac8762
8547d80
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,9 @@ public struct RadixConnectClient: DependencyKey, Sendable { | |
public var addP2PWithPassword: AddP2PWithPassword | ||
|
||
public var receiveMessages: ReceiveMessages | ||
public var sendMessage: SendMessage | ||
|
||
public var sendResponse: SendResponse | ||
public var sendRequest: SendRequest | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A request is a new message, typically a request to Connector extension to execute some Ledger Hardware device command, recipient RTC peer is unknown, see |
||
} | ||
|
||
extension RadixConnectClient { | ||
|
@@ -39,6 +41,9 @@ extension RadixConnectClient { | |
public typealias AddP2PWithPassword = @Sendable (ConnectionPassword) async throws -> Void | ||
public typealias DeleteP2PLinkByPassword = @Sendable (ConnectionPassword) async throws -> Void | ||
|
||
public typealias ReceiveMessages = @Sendable () async -> AsyncStream<P2P.RTCIncomingMessageResult> | ||
public typealias SendMessage = @Sendable (P2P.RTCOutgoingMessage) async throws -> Void | ||
public typealias ReceiveMessages = @Sendable () async -> AnyAsyncSequence<P2P.RTCIncomingMessage> | ||
|
||
public typealias SendRequest = @Sendable (_ request: P2P.RTCOutgoingMessage.Request, _ sendStrategy: P2P.RTCOutgoingMessage.Request.SendStrategy) async throws -> Void | ||
|
||
public typealias SendResponse = @Sendable (_ response: P2P.RTCOutgoingMessage.Response, _ origin: P2P.RTCRoute) async throws -> Void | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import RadixConnectModels | ||
|
||
extension P2P { | ||
/// Recipient of sender of an RTC message | ||
public struct RTCRoute: Sendable, Hashable { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A since long missing tuple with the information on HOW to send an RTC message. |
||
/// The PerPeerPairConnection password. | ||
public let connectionId: ConnectionPassword | ||
/// ID to a specific peer **connection** for some PerPeerPairConnection. | ||
public let peerConnectionId: PeerConnectionID | ||
|
||
public init(connectionId: ConnectionPassword, peerConnectionId: PeerConnectionID) { | ||
self.connectionId = connectionId | ||
self.peerConnectionId = peerConnectionId | ||
} | ||
} | ||
|
||
/// An incoming message over RTC from some `route`, might have failed | ||
/// or succeeded to receive and decode, which is why this contains a | ||
/// `result` and not an `P2P.RTCMessageFromPeer` directly. | ||
public typealias RTCIncomingMessage = RTCIncomingMessageContainer<P2P.RTCMessageFromPeer> | ||
|
||
/// An incoming Dapp Request over RTC from some `route`, might have failed | ||
/// or succeeded to receive and decode, which is why this contains a | ||
/// `result` and not an `P2P.Dapp.Request` directly. | ||
public typealias RTCIncomingDappRequest = RTCIncomingMessageContainer<P2P.Dapp.Request> | ||
|
||
/// An incoming message over RTC from some `route`, might have failed | ||
/// or succeeded to receive and decode, which is why this contains a | ||
/// `result` and not an `P2P.RTCMessageFromPeer` directly. | ||
public struct RTCIncomingMessageContainer<Success: Sendable & Hashable>: Sendable, Hashable { | ||
public let result: Result<Success, Error> | ||
public let route: RTCRoute | ||
public init(result: Result<Success, Error>, route: RTCRoute) { | ||
self.result = result | ||
self.route = route | ||
} | ||
} | ||
} | ||
|
||
extension P2P.RTCIncomingMessageContainer { | ||
public static func == (lhs: Self, rhs: Self) -> Bool { | ||
guard lhs.route == rhs.route else { | ||
return false | ||
} | ||
switch (lhs.result, rhs.result) { | ||
case let (.failure(lhsFailure), .failure(rhsFailure)): | ||
// FIXME: strongly type messages? to an Error type which is Hashable? | ||
return String(describing: lhsFailure) == String(describing: rhsFailure) | ||
case let (.success(lhsSuccess), .success(rhsSuccess)): | ||
return lhsSuccess == rhsSuccess | ||
|
||
default: return false | ||
} | ||
} | ||
|
||
public func hash(into hasher: inout Hasher) { | ||
hasher.combine(route) | ||
switch result { | ||
case let .failure(error): | ||
hasher.combine(String(describing: error)) | ||
case let .success(success): | ||
hasher.combine(success) | ||
} | ||
} | ||
|
||
public func unpackMap<NewSuccess>( | ||
_ transform: (Success) -> NewSuccess? | ||
) -> P2P.RTCIncomingMessageContainer<NewSuccess>? { | ||
switch result { | ||
case let .failure(error): return .init(result: .failure(error), route: route) | ||
case let .success(value): | ||
guard let transformed = transform(value) else { | ||
return nil | ||
} | ||
return .init(result: .success(transformed), route: route) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import RadixConnectModels | ||
|
||
// MARK: - P2P.RTCMessageFromPeer | ||
extension P2P { | ||
/// A successfully received and decoded message from a peer | ||
/// either a `response` or a `request`. | ||
public enum RTCMessageFromPeer: Sendable, Hashable { | ||
/// A response from a peer to some request we have sent over RTC | ||
case response(Response) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @GhenadieVP I was able to remove the |
||
|
||
/// A request coming from some peer over RTC | ||
case request(Request) | ||
|
||
/// A response from a peer to some request we have sent. | ||
public enum Response: Sendable, Hashable, Equatable, Decodable { | ||
case connectorExtension(P2P.ConnectorExtension.Response) | ||
} | ||
|
||
public enum Request: Sendable, Hashable, Equatable, Decodable { | ||
case dapp(P2P.Dapp.Request) | ||
} | ||
} | ||
} | ||
|
||
extension P2P.RTCMessageFromPeer.Request { | ||
public init(from decoder: Decoder) throws { | ||
self = try .dapp(.init(from: decoder)) | ||
} | ||
} | ||
|
||
extension P2P.RTCMessageFromPeer.Response { | ||
public init(from decoder: Decoder) throws { | ||
self = try .connectorExtension(.init(from: decoder)) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import RadixConnectModels | ||
|
||
// MARK: - P2P.RTCOutgoingMessage | ||
extension P2P { | ||
/// A message to be sent to some peer over WebRTC | ||
/// it might be either a response to some original | ||
/// incoming request, or it might be a request initiated | ||
/// by our wallet. | ||
public enum RTCOutgoingMessage: Sendable, Hashable { | ||
/// A response to some request that we received from `origin`, | ||
/// we will use `origin` to identify the RTC channel to send over. | ||
case response(Response, origin: RTCRoute) | ||
|
||
/// A request initiated by us, sent over RTC using `sendStrategy`. | ||
case request(Request, sendStrategy: Request.SendStrategy) | ||
|
||
/// A response to some request that we received from `origin`, | ||
/// we will use `origin` to identify the RTC channel to send over. | ||
public enum Response: Sendable, Hashable, Encodable { | ||
/// Response back to Dapps | ||
case dapp(P2P.Dapp.Response) | ||
} | ||
|
||
/// A request initiated by us, sent over RTC using `SendStrategy`. | ||
public enum Request: Sendable, Hashable, Encodable { | ||
/// Describes the strategy used to find a RTC peer to send a request to. | ||
public enum SendStrategy: Sendable, Hashable, Equatable { | ||
/// Sends a request to ALL P2PLinks | ||
case broadcastToAllPeers | ||
} | ||
|
||
/// e.g. for Ledger Nano interaction, `PeerConnectionID` is not known | ||
case connectorExtension(P2P.ConnectorExtension.Request) | ||
} | ||
} | ||
} | ||
|
||
extension P2P.RTCOutgoingMessage.Response { | ||
public func encode(to encoder: Encoder) throws { | ||
switch self { | ||
case let .dapp(response): | ||
try response.encode(to: encoder) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A response is for now typically a response back to a Dapp for some "wallet interaction".