Skip to content

Commit

Permalink
Fix crash caused by early profile access (#1401)
Browse files Browse the repository at this point in the history
  • Loading branch information
GhenadieVP authored Nov 28, 2024
1 parent b4ad24e commit df94838
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ struct RadixConnectClient: DependencyKey, Sendable {
var sendRequest: SendRequest

var handleDappDeepLink: HandleDappDeepLink

var startNotifyingConnectorWithAccounts: StartNotifyingConnectorWithAccounts
}

extension RadixConnectClient {
Expand Down Expand Up @@ -70,4 +72,6 @@ extension RadixConnectClient {

typealias ConnectToP2PLinks = @Sendable (P2PLinks) async throws -> Void
typealias HandleDappDeepLink = @Sendable (URL) async throws -> Void

typealias StartNotifyingConnectorWithAccounts = @Sendable () async throws -> Void
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,6 @@ extension RadixConnectClient {
let radixConnectMobile = RadixConnectMobile()
let localNetworkAuthorization = LocalNetworkAuthorization()

Task {
@Dependency(\.accountsClient) var accountsClient
for try await accounts in await accountsClient.accountsOnCurrentNetwork() {
guard !Task.isCancelled else { return }
try? await sendAccountListMessage(accounts: accounts)
}
}

Task {
let connectedClients = await rtcClients.connectClients()
.filter { updates in
!updates.flatMap(\.idsOfConnectedPeerConnections).isEmpty
}
for try await updates in connectedClients {
guard !Task.isCancelled else { return }
sendAccountListMessageAfterConnect()
}
}

@Sendable
func sendAccountListMessageAfterConnect() {
Task {
Expand Down Expand Up @@ -176,6 +157,28 @@ extension RadixConnectClient {
errorQueue.schedule(error)
throw error
}
},
startNotifyingConnectorWithAccounts: {
try await withThrowingTaskGroup(of: Void.self) { group in
group.addTask {
@Dependency(\.accountsClient) var accountsClient
for try await accounts in await accountsClient.accountsOnCurrentNetwork() {
guard !Task.isCancelled else { return }
try? await sendAccountListMessage(accounts: accounts)
}
}

group.addTask {
let connectedClients = await rtcClients.connectClients()
.filter { updates in
!updates.flatMap(\.idsOfConnectedPeerConnections).isEmpty
}
for try await updates in connectedClients {
guard !Task.isCancelled else { return }
sendAccountListMessageAfterConnect()
}
}
}
}
)
}()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ extension RadixConnectClient: TestDependencyKey {
receiveMessages: unimplemented("\(Self.self).receiveMessages"),
sendResponse: unimplemented("\(Self.self).sendResponse"),
sendRequest: unimplemented("\(Self.self).sendRequest"),
handleDappDeepLink: unimplemented("\(Self.self).sendRequest")
handleDappDeepLink: unimplemented("\(Self.self).sendRequest"),
startNotifyingConnectorWithAccounts: unimplemented("\(Self.self).startNotifyingConnectorWithAccounts")
)
}

Expand All @@ -37,7 +38,8 @@ extension RadixConnectClient {
receiveMessages: { AsyncLazySequence([]).eraseToAnyAsyncSequence() },
sendResponse: { _, _ in },
sendRequest: { _, _ in 0 },
handleDappDeepLink: { _ in }
handleDappDeepLink: { _ in },
startNotifyingConnectorWithAccounts: {}
)
}
#endif // DEBUG
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ extension AccountRecoveryScanInProgress.State {

private var isManualScan: Bool {
switch mode {
case .privateHD:
case .createProfile:
false
case .factorSourceWithID:
case .addAccounts:
true
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ struct AccountRecoveryScanInProgress: Sendable, FeatureReducer {
var destination: Destination.State? = nil

enum Mode: Sendable, Hashable {
case privateHD(PrivateHierarchicalDeterministicFactorSource)
case factorSourceWithID(id: FactorSourceIDFromHash, Loadable<FactorSource> = .idle)
case createProfile(PrivateHierarchicalDeterministicFactorSource)
case addAccounts(factorSourceId: FactorSourceIDFromHash, Loadable<FactorSource> = .idle)
}

var factorSourceIDFromHash: FactorSourceIDFromHash {
switch mode {
case let .privateHD(privateHD):
case let .createProfile(privateHD):
privateHD.factorSource.id
case let .factorSourceWithID(id, _):
case let .addAccounts(id, _):
id
}
}
Expand Down Expand Up @@ -110,20 +110,19 @@ struct AccountRecoveryScanInProgress: Sendable, FeatureReducer {
private let destinationPath: WritableKeyPath<State, PresentationState<Destination.State>> = \.$destination

@Dependency(\.dismiss) var dismiss
@Dependency(\.accountsClient) var accountsClient
@Dependency(\.factorSourcesClient) var factorSourcesClient
@Dependency(\.onLedgerEntitiesClient) var onLedgerEntitiesClient

func reduce(into state: inout State, internalAction: InternalAction) -> Effect<Action> {
switch internalAction {
case .initiate:
switch state.mode {
case .privateHD:
case .createProfile:
return derivePublicKeys(state: &state)
case .factorSourceWithID:
case .addAccounts:
state.status = .loadingFactorSource
let id = state.factorSourceIDFromHash
state.mode = .factorSourceWithID(id: id, .loading)
state.mode = .addAccounts(factorSourceId: id, .loading)
return .run { [forOlympiaAccounts = state.forOlympiaAccounts] send in
let result = await TaskResult<IndicesUsedByFactorSource> {
try await factorSourcesClient.indicesOfEntitiesControlledByFactorSource(
Expand Down Expand Up @@ -151,8 +150,8 @@ struct AccountRecoveryScanInProgress: Sendable, FeatureReducer {
state.networkID = networkID
}

state.mode = .factorSourceWithID(
id: state.factorSourceIDFromHash,
state.mode = .addAccounts(
factorSourceId: state.factorSourceIDFromHash,
.success(
indicesUsedByFactorSource.factorSource
)
Expand Down Expand Up @@ -217,10 +216,14 @@ struct AccountRecoveryScanInProgress: Sendable, FeatureReducer {
assert(factorSourceID == id.asGeneral)
assert(networkID == state.networkID)
loggerGlobal.debug("Creating accounts with networkID: \(networkID)")
return .run { send in
return .run { [mode = state.mode] send in
let accounts = await publicHDKeys.enumerated().asyncMap { localOffset, publicHDKey in
let offset = localOffset + globalOffset
let appearanceID = await accountsClient.nextAppearanceID(networkID, offset)
let appearanceID = await getAccountAppearanceID(
mode: mode,
offset: offset,
networkID: networkID
)
return Account(
networkID: networkID,
factorInstance: .init(factorSourceId: id, publicKey: publicHDKey),
Expand Down Expand Up @@ -256,6 +259,20 @@ struct AccountRecoveryScanInProgress: Sendable, FeatureReducer {
func reduceDismissedDestination(into state: inout State) -> Effect<Action> {
.run { _ in await dismiss() }
}

private func getAccountAppearanceID(
mode: State.Mode,
offset: Int,
networkID: NetworkID
) async -> AppearanceID {
switch mode {
case .createProfile:
return AppearanceID.fromNumberOfAccounts(offset)
case .addAccounts:
@Dependency(\.accountsClient) var accountsClient
return await accountsClient.nextAppearanceID(networkID, offset)
}
}
}

extension AccountRecoveryScanInProgress {
Expand Down Expand Up @@ -305,7 +322,7 @@ extension AccountRecoveryScanInProgress {
}
let factorSourceOption: DerivePublicKeys.State.FactorSourceOption
switch state.mode {
case let .factorSourceWithID(_, loadableState):
case let .addAccounts(_, loadableState):
switch loadableState {
case let .success(factorSource):
factorSourceOption = .specific(factorSource)
Expand All @@ -315,7 +332,7 @@ extension AccountRecoveryScanInProgress {
assertionFailure(errorMsg)
return .send(.delegate(.failed))
}
case let .privateHD(privateHDFactorSource):
case let .createProfile(privateHDFactorSource):
factorSourceOption = .specificPrivateHDFactorSource(privateHDFactorSource)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ struct AccountRecoveryScanCoordinator: Sendable, FeatureReducer {
switch purpose {
case let .addAccounts(id, forOlympiaAccounts):
AccountRecoveryScanInProgress.State(
mode: .factorSourceWithID(id: id),
mode: .addAccounts(factorSourceId: id),
forOlympiaAccounts: forOlympiaAccounts
)

case let .createProfile(privateHDFactorSource):
AccountRecoveryScanInProgress.State(
mode: .privateHD(privateHDFactorSource),
mode: .createProfile(privateHDFactorSource),
forOlympiaAccounts: false
)
}
Expand Down
12 changes: 12 additions & 0 deletions RadixWallet/Features/MainFeature/Main+Reducer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ struct Main: Sendable, FeatureReducer {
@Dependency(\.securityCenterClient) var securityCenterClient
@Dependency(\.accountLockersClient) var accountLockersClient
@Dependency(\.deepLinkHandlerClient) var deepLinkHandlerClient
@Dependency(\.radixConnectClient) var radixConnectClient

init() {}

Expand All @@ -82,6 +83,7 @@ struct Main: Sendable, FeatureReducer {
.merge(with: startMonitoringSecurityCenterEffect())
.merge(with: startMonitoringAccountLockersEffect())
.merge(with: gatewayValuesEffect())
.merge(with: startNotifyingConnectorWithAccounts())
}
}

Expand Down Expand Up @@ -125,6 +127,16 @@ struct Main: Sendable, FeatureReducer {
}
}

private func startNotifyingConnectorWithAccounts() -> Effect<Action> {
.run { _ in
do {
try await radixConnectClient.startNotifyingConnectorWithAccounts()
} catch {
loggerGlobal.notice("radixConnectClient.startNotifyingConnectorWithAccounts failed: \(error)")
}
}
}

func reduce(into state: inout State, childAction: ChildAction) -> Effect<Action> {
switch childAction {
case .home(.delegate(.displaySettings)):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ final class MainFeatureTests: TestCase {
.dependency(\.securityCenterClient, .noop)
.dependency(\.deepLinkHandlerClient, .noop)
.dependency(\.accountLockersClient, .noop)
.dependency(\.radixConnectClient, .noop)
}

XCTAssertFalse(store.state.showIsUsingTestnetBanner)
Expand Down

0 comments on commit df94838

Please sign in to comment.