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

[ABW-3230] Use Wallet Interaction models from Sargon #1171

Merged
merged 13 commits into from
Jun 21, 2024
156 changes: 12 additions & 144 deletions RadixWallet.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/radixdlt/sargon",
"state" : {
"revision" : "37221d388f75bdf4ce2ef9d2e4ed6fa686072969",
"version" : "1.0.7"
"revision" : "4152cd3458aec0eae06aee7376414bcaeb5d9d14",
"version" : "1.0.11"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,21 @@ extension DappInteractionClient {
case accountTransfer
}

public typealias AddWalletInteraction = @Sendable (_ items: P2P.Dapp.Request.Items, _ interaction: WalletInteraction) async -> P2P.RTCOutgoingMessage.Response?
public typealias AddWalletInteraction = @Sendable (_ items: DappToWalletInteractionItems, _ interaction: WalletInteraction) async -> P2P.RTCOutgoingMessage.Response?
public typealias CompleteInteraction = @Sendable (P2P.RTCOutgoingMessage) async throws -> Void
}

extension P2P.Dapp.Request.ID {
extension WalletInteractionId {
public static func walletInteractionID(for interaction: DappInteractionClient.WalletInteraction) -> Self {
"\(interaction.rawValue)_\(UUID().uuidString)"
}

public var isWalletAccountDepositSettingsInteraction: Bool {
rawValue.hasPrefix(DappInteractionClient.WalletInteraction.accountDepositSettings.rawValue)
hasPrefix(DappInteractionClient.WalletInteraction.accountDepositSettings.rawValue)
Copy link
Contributor

Choose a reason for hiding this comment

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

We are now using WalletInteractionId, which is a typealias of UUID. Then, how can it contain a prefix that we manually set on line 29?

Copy link
Contributor Author

@danvleju-rdx danvleju-rdx Jun 14, 2024

Choose a reason for hiding this comment

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

WalletInteractionId is a typealias of String for now. Wrote an explanation here.

Copy link
Contributor

Choose a reason for hiding this comment

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

oh, I was navigating to an oudated typealias.
Thanks

}

public var isWalletAccountTransferInteraction: Bool {
rawValue.hasPrefix(DappInteractionClient.WalletInteraction.accountTransfer.rawValue)
hasPrefix(DappInteractionClient.WalletInteraction.accountTransfer.rawValue)
}

public var isWalletInteraction: Bool {
Expand All @@ -46,9 +46,9 @@ extension P2P.Dapp.Request.ID {
extension DappInteractionClient {
public struct RequestEnvelope: Sendable, Hashable {
public let route: P2P.Route
public let request: P2P.Dapp.Request
public let request: DappToWalletInteraction

public init(route: P2P.Route, request: P2P.Dapp.Request) {
public init(route: P2P.Route, request: DappToWalletInteraction) {
self.route = route
self.request = request
}
Expand All @@ -64,12 +64,12 @@ extension DappInteractionClient {
}

public enum Request: Sendable, Hashable {
case valid(P2P.Dapp.Request)
case invalid(request: P2P.Dapp.RequestUnvalidated, reason: InvalidRequestReason)
case valid(DappToWalletInteraction)
case invalid(request: DappToWalletInteractionUnvalidated, reason: InvalidRequestReason)
}

public enum InvalidRequestReason: Sendable, Hashable {
case incompatibleVersion(connectorExtensionSent: P2P.Dapp.Version, walletUses: P2P.Dapp.Version)
case incompatibleVersion(connectorExtensionSent: WalletInteractionVersion, walletUses: WalletInteractionVersion)
case wrongNetworkID(connectorExtensionSent: NetworkID, walletUses: NetworkID)
case invalidDappDefinitionAddress(gotStringWhichIsAnInvalidAccountAddress: String)
case invalidOrigin(invalidURLString: String)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ extension DappInteractionClient: DependencyKey {
addWalletInteraction: { items, interaction in
@Dependency(\.gatewaysClient) var gatewaysClient

let id: P2P.Dapp.Request.ID = .walletInteractionID(for: interaction)
let interactionId: WalletInteractionId = .walletInteractionID(for: interaction)

let request = await ValidatedDappRequest(
route: .wallet,
request: .valid(
.init(
id: id,
interactionId: interactionId,
items: items,
metadata: .init(
version: P2P.Dapp.currentVersion,
version: .current,
networkId: gatewaysClient.getCurrentNetworkID(),
origin: DappOrigin.wallet,
dAppDefinitionAddress: .wallet
origin: DappToWalletInteractionMetadata.Origin.wallet,
danvleju-rdx marked this conversation as resolved.
Show resolved Hide resolved
dappDefinitionAddress: .wallet
)
))
)
Expand All @@ -46,7 +46,7 @@ extension DappInteractionClient: DependencyKey {
return await interactionResponsesSubject.first(where: {
switch $0 {
case let .dapp(response):
response.id == id
response.interactionId == interactionId
}
})
},
Expand All @@ -68,15 +68,15 @@ extension DappInteractionClient: DependencyKey {
extension DappInteractionClient {
/// Validates a received request from Dapp.
static func validate(
_ message: P2P.RTCIncomingMessageContainer<P2P.Dapp.RequestUnvalidated>
_ message: P2P.RTCIncomingMessageContainer<DappToWalletInteractionUnvalidated>
) async -> Result<ValidatedDappRequest, Error> {
@Dependency(\.appPreferencesClient) var appPreferencesClient
@Dependency(\.gatewaysClient) var gatewaysClient
@Dependency(\.rolaClient) var rolaClient

let route = message.route

let nonValidated: P2P.Dapp.RequestUnvalidated
let nonValidated: DappToWalletInteractionUnvalidated

do {
nonValidated = try message.result.get()
Expand All @@ -89,8 +89,8 @@ extension DappInteractionClient {
}

let nonvalidatedMeta = nonValidated.metadata
guard P2P.Dapp.currentVersion == nonvalidatedMeta.version else {
return invalidRequest(.incompatibleVersion(connectorExtensionSent: nonvalidatedMeta.version, walletUses: P2P.Dapp.currentVersion))
guard WalletInteractionVersion.current == nonvalidatedMeta.version else {
return invalidRequest(.incompatibleVersion(connectorExtensionSent: nonvalidatedMeta.version, walletUses: .current))
}
let currentNetworkID = await gatewaysClient.getCurrentNetworkID()
guard currentNetworkID == nonValidated.metadata.networkId else {
Expand All @@ -100,37 +100,33 @@ extension DappInteractionClient {
let dappDefinitionAddress: DappDefinitionAddress
do {
dappDefinitionAddress = try DappDefinitionAddress(
validatingAddress: nonValidated.metadata.dAppDefinitionAddress
validatingAddress: nonValidated.metadata.dappDefinitionAddress
)
} catch {
return invalidRequest(.invalidDappDefinitionAddress(gotStringWhichIsAnInvalidAccountAddress: nonvalidatedMeta.dAppDefinitionAddress))
return invalidRequest(.invalidDappDefinitionAddress(gotStringWhichIsAnInvalidAccountAddress: nonvalidatedMeta.dappDefinitionAddress))
}

if case let .request(readRequest) = nonValidated.items {
switch readRequest {
case let .authorized(authorized):
if authorized.oneTimeAccounts?.numberOfAccounts.isValid == false {
return invalidRequest(.badContent(.numberOfAccountsInvalid))
}
if authorized.ongoingAccounts?.numberOfAccounts.isValid == false {
return invalidRequest(.badContent(.numberOfAccountsInvalid))
}
case let .unauthorized(unauthorized):
if unauthorized.oneTimeAccounts?.numberOfAccounts.isValid == false {
return invalidRequest(.badContent(.numberOfAccountsInvalid))
}
switch nonValidated.items {
case let .authorizedRequest(authorized):
if authorized.oneTimeAccounts?.numberOfAccounts.isValid == false {
return invalidRequest(.badContent(.numberOfAccountsInvalid))
}
if authorized.ongoingAccounts?.numberOfAccounts.isValid == false {
return invalidRequest(.badContent(.numberOfAccountsInvalid))
}
case let .unauthorizedRequest(unauthorized):
if unauthorized.oneTimeAccounts?.numberOfAccounts.isValid == false {
return invalidRequest(.badContent(.numberOfAccountsInvalid))
}
default:
break
}

guard let origin = try? DappOrigin(string: nonvalidatedMeta.origin) else {
return invalidRequest(.invalidOrigin(invalidURLString: nonvalidatedMeta.origin))
}

let metadataValidDappDefAddress = P2P.Dapp.Request.Metadata(
let metadataValidDappDefAddress = DappToWalletInteractionMetadata(
version: nonvalidatedMeta.version,
networkId: nonvalidatedMeta.networkId,
origin: origin,
dAppDefinitionAddress: dappDefinitionAddress
origin: nonvalidatedMeta.origin,
dappDefinitionAddress: dappDefinitionAddress
)

let isDeveloperModeEnabled = await appPreferencesClient.isDeveloperModeEnabled()
Expand All @@ -148,7 +144,7 @@ extension DappInteractionClient {
.init(
route: route,
request: .valid(.init(
id: nonValidated.id,
interactionId: nonValidated.interactionId,
items: nonValidated.items,
metadata: metadataValidDappDefAddress
))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,15 @@ public struct SignTransactionWithLedgerRequest: Sendable, Hashable {
public struct SignAuthChallengeWithLedgerRequest: Sendable, Hashable {
public let signers: NonEmpty<IdentifiedArrayOf<Signer>>
public let ledger: LedgerHardwareWalletFactorSource
public let challenge: P2P.Dapp.Request.AuthChallengeNonce
public let origin: P2P.Dapp.Request.Metadata.Origin
public let challenge: DappToWalletInteractionAuthChallengeNonce
public let origin: DappToWalletInteractionMetadata.Origin
public let dAppDefinitionAddress: AccountAddress

public init(
ledger: LedgerHardwareWalletFactorSource,
signers: NonEmpty<IdentifiedArrayOf<Signer>>,
challenge: P2P.Dapp.Request.AuthChallengeNonce,
origin: P2P.Dapp.Request.Metadata.Origin,
challenge: DappToWalletInteractionAuthChallengeNonce,
origin: DappToWalletInteractionMetadata.Origin,
dAppDefinitionAddress: AccountAddress
) {
self.ledger = ledger
Expand Down
12 changes: 6 additions & 6 deletions RadixWallet/Clients/ROLAClient/ROLAClient+Interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public struct ROLAClient: Sendable, DependencyKey {

// MARK: ROLAClient.PerformWellKnownFileCheck
extension ROLAClient {
public typealias PerformDappDefinitionVerification = @Sendable (P2P.Dapp.Request.Metadata) async throws -> Void
public typealias PerformWellKnownFileCheck = @Sendable (P2P.Dapp.Request.Metadata) async throws -> Void
public typealias PerformDappDefinitionVerification = @Sendable (DappToWalletInteractionMetadata) async throws -> Void
public typealias PerformWellKnownFileCheck = @Sendable (DappToWalletInteractionMetadata) async throws -> Void
public typealias ManifestForAuthKeyCreation = @Sendable (ManifestForAuthKeyCreationRequest) async throws -> TransactionManifest
public typealias AuthenticationDataToSignForChallenge = @Sendable (AuthenticationDataToSignForChallengeRequest) throws -> AuthenticationDataToSignForChallengeResponse
}
Expand All @@ -28,13 +28,13 @@ extension DependencyValues {

// MARK: - AuthenticationDataToSignForChallengeRequest
public struct AuthenticationDataToSignForChallengeRequest: Sendable, Hashable {
public let challenge: P2P.Dapp.Request.AuthChallengeNonce
public let origin: P2P.Dapp.Request.Metadata.Origin
public let challenge: DappToWalletInteractionAuthChallengeNonce
public let origin: DappToWalletInteractionMetadata.Origin
public let dAppDefinitionAddress: DappDefinitionAddress

public init(
challenge: P2P.Dapp.Request.AuthChallengeNonce,
origin: P2P.Dapp.Request.Metadata.Origin,
challenge: DappToWalletInteractionAuthChallengeNonce,
origin: DappToWalletInteractionMetadata.Origin,
dAppDefinitionAddress: DappDefinitionAddress
) {
self.challenge = challenge
Expand Down
14 changes: 7 additions & 7 deletions RadixWallet/Clients/ROLAClient/ROLAClient+Live.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ extension ROLAClient {
return Self(
performDappDefinitionVerification: { metadata async throws in
_ = try await onLedgerEntitiesClient.getDappMetadata(
metadata.dAppDefinitionAddress,
validatingWebsite: metadata.origin.url
metadata.dappDefinitionAddress,
Copy link
Contributor

Choose a reason for hiding this comment

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

mm we are using dAppXYZ all over the app, was this approved on Sargon?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The variable name in Rust is dapp_definition_address, so it's exported as dappDefinitionAddress. Do you know any trick to have it like dAppDefinitionAddress? :)

Copy link
Contributor

Choose a reason for hiding this comment

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

On the one hand dApp is the correct style, on the other hand we did decide to generally write it Dapp, while would lead to dapp... for instances/enum cases, and Dapp... for types. But as you point out, we only seem to follow this convention for types.

validatingWebsite: metadata.origin
)
},
performWellKnownFileCheck: { metadata async throws in
@Dependency(\.urlSession) var urlSession

let originURL = metadata.origin.url
let originURL = metadata.origin

let url = originURL.appending(path: Constants.wellKnownFilePath)

Expand Down Expand Up @@ -73,7 +73,7 @@ extension ROLAClient {
let response = try await fetchWellKnownFile()

let dAppDefinitionAddresses = response.dApps.map(\.dAppDefinitionAddress)
guard dAppDefinitionAddresses.contains(metadata.dAppDefinitionAddress) else {
guard dAppDefinitionAddresses.contains(metadata.dappDefinitionAddress) else {
throw ROLAFailure.unknownDappDefinitionAddress
}
},
Expand Down Expand Up @@ -115,13 +115,13 @@ extension ROLAClient {
extension ROLAClient {
/// `0x52 || challenge(32) || L_dda(1) || dda_utf8(L_dda) || origin_utf8`
static func payloadToHash(
challenge: P2P.Dapp.Request.AuthChallengeNonce,
challenge: DappToWalletInteractionAuthChallengeNonce,
dAppDefinitionAddress accountAddress: AccountAddress,
origin metadataOrigin: P2P.Dapp.Request.Metadata.Origin
origin metadataOrigin: DappToWalletInteractionMetadata.Origin
) -> Data {
let rPrefix: UInt8 = 0x52
let dAppDefinitionAddress = accountAddress.address
let origin = metadataOrigin.urlString.rawValue
let origin = metadataOrigin.absoluteString
precondition(dAppDefinitionAddress.count <= UInt8.max)
let challengeBytes = [UInt8](challenge.data.data)
let lengthDappDefinitionAddress = UInt8(dAppDefinitionAddress.count)
Expand Down
3 changes: 2 additions & 1 deletion RadixWallet/Clients/ROLAClient/ROLAFailure.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import Sargon

public enum ROLAFailure: Sendable, LocalizedError, Equatable {
case wrongAccountType
Expand All @@ -21,7 +22,7 @@ public enum ROLAFailure: Sendable, LocalizedError, Equatable {
}
}

public var errorKindAndMessage: (errorKind: P2P.Dapp.Response.WalletInteractionFailureResponse.ErrorType, message: String?) {
public var errorKindAndMessage: (errorKind: DappWalletInteractionErrorType, message: String?) {
switch self {
case .wrongAccountType:
(errorKind: .wrongAccountType, message: errorDescription)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ extension RadixConnectClient {
func sendAccountListMessage(accounts: Accounts) async throws {
let encoder = jsonEncoder()
let accounts = accounts.map {
P2P.Dapp.Response.WalletAccount(
accountAddress: $0.address,
WalletInteractionWalletAccount(
address: $0.address,
label: $0.displayName,
appearanceId: $0.appearanceID
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public enum TransactionFailure: Sendable, LocalizedError, Equatable {
}

extension TransactionFailure {
public var errorKindAndMessage: (errorKind: P2P.Dapp.Response.WalletInteractionFailureResponse.ErrorType, message: String?) {
public var errorKindAndMessage: (errorKind: DappWalletInteractionErrorType, message: String?) {
switch self {
case let .failedToPrepareForTXSigning(error), let .failedToPrepareTXReview(.failedSigning(error)):
switch error {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ extension P2P {

/// 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 RTCIncomingDappNonValidatedRequest = RTCIncomingMessageContainer<P2P.Dapp.RequestUnvalidated>
/// `result` and not an `DappToWalletInteraction` directly.
public typealias RTCIncomingDappNonValidatedRequest = RTCIncomingMessageContainer<DappToWalletInteractionUnvalidated>

/// An incoming message over RTC from some `route`, might have failed
/// or succeeded to receive and decode, which is why this contains a
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,24 @@ extension P2P {
}

public enum Request: Sendable, Hashable, Equatable, Decodable {
case dapp(P2P.Dapp.RequestUnvalidated)
case dapp(DappToWalletInteractionUnvalidated)
}
}
}

extension P2P.RTCMessageFromPeer.Request {
Copy link
Contributor

Choose a reason for hiding this comment

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

Small improvement maybe - we could remove the Codable conformance from Request, and then decode the DappToWalletInteractionUnvalidated separately and embed it in the request afterwards.

public init(from decoder: Decoder) throws {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we actually need this to be generally Decodable?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed Decodable

self = try .dapp(.init(from: decoder))
@Dependency(\.jsonEncoder) var jsonEncoder

let container = try decoder.singleValueContainer()
let jsonValue = try container.decode(JSONValue.self)
let jsonData = try jsonEncoder().encode(jsonValue.dictionary ?? [:])

guard let jsonString = String(data: jsonData, encoding: .utf8) else {
throw DecodingError.dataCorruptedError(in: container, debugDescription: "Invalid data")
}

self = try .dapp(.init(jsonString: jsonString))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ extension P2P {
/// 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)
case dapp(WalletToDappInteractionResponse)
}

/// A request initiated by us, sent over RTC using `SendStrategy`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ extension P2P.ConnectorExtension.Request {
public struct SignAuthChallenge: Sendable, Hashable, Encodable {
public let signers: [P2P.LedgerHardwareWallet.KeyParameters]
public let ledgerDevice: P2P.LedgerHardwareWallet.LedgerDevice
public let challenge: P2P.Dapp.Request.AuthChallengeNonce
public let origin: P2P.Dapp.Request.Metadata.Origin
public let challenge: DappToWalletInteractionAuthChallengeNonce
public let origin: DappToWalletInteractionMetadata.Origin
public let dAppDefinitionAddress: AccountAddress

public init(
signers: [P2P.LedgerHardwareWallet.KeyParameters],
ledgerDevice: P2P.LedgerHardwareWallet.LedgerDevice,
challenge: P2P.Dapp.Request.AuthChallengeNonce,
origin: P2P.Dapp.Request.Metadata.Origin,
challenge: DappToWalletInteractionAuthChallengeNonce,
origin: DappToWalletInteractionMetadata.Origin,
dAppDefinitionAddress: AccountAddress
) {
self.signers = signers
Expand Down Expand Up @@ -163,6 +163,6 @@ extension P2P.ConnectorExtension.Request {
}

public let discriminator: Discriminator
public let accounts: [P2P.Dapp.Response.WalletAccount]
public let accounts: [WalletInteractionWalletAccount]
}
}

This file was deleted.

Loading
Loading