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-1868] Replace factor source based counters with entityIndex #602

Merged
merged 14 commits into from
Aug 14, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,7 @@ let instabridge = """
{
"model": "",
"name": ""
},
"nextDerivationIndicesPerNetwork":
[]
}
},
"discriminator": "device"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,7 @@ let bestFriend = """
{
"model": "",
"name": ""
},
"nextDerivationIndicesPerNetwork":
[]
}
},
"discriminator": "device"
}
Expand Down Expand Up @@ -352,9 +350,7 @@ let instabridge = """
{
"model": "",
"name": ""
},
"nextDerivationIndicesPerNetwork":
[]
}
},
"discriminator": "device"
}
Expand Down Expand Up @@ -520,9 +516,7 @@ let colleague = """
{
"model": "",
"name": ""
},
"nextDerivationIndicesPerNetwork":
[]
}
},
"discriminator": "device"
}
Expand Down
4 changes: 3 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -193,9 +193,11 @@ package.addModules([
name: "DerivePublicKeysFeature",
featureSuffixDroppedFromFolderName: true,
dependencies: [
"AccountsClient",
"DeviceFactorSourceClient",
"FactorSourcesClient",
"LedgerHardwareWalletClient",
"DeviceFactorSourceClient",
"PersonasClient",
],
tests: .no
),
Expand Down
8 changes: 5 additions & 3 deletions Sources/Clients/AccountsClient/AccountsClient+Interface.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Profile
// MARK: - AccountsClient
public struct AccountsClient: Sendable {
public var getCurrentNetworkID: GetCurrentNetworkID
public var nextAccountIndex: NextAccountIndex

/// Accounts on current network (active gateway)
public var getAccountsOnCurrentNetwork: GetAccountsOnCurrentNetwork
Expand All @@ -30,6 +31,7 @@ public struct AccountsClient: Sendable {

public init(
getCurrentNetworkID: @escaping GetCurrentNetworkID,
nextAccountIndex: @escaping NextAccountIndex,
getAccountsOnCurrentNetwork: @escaping GetAccountsOnCurrentNetwork,
accountsOnCurrentNetwork: @escaping AccountsOnCurrentNetwork,
getAccountsOnNetwork: @escaping GetAccountsOnNetwork,
Expand All @@ -40,6 +42,7 @@ public struct AccountsClient: Sendable {
updateAccount: @escaping UpdateAccount
) {
self.getCurrentNetworkID = getCurrentNetworkID
self.nextAccountIndex = nextAccountIndex
self.getAccountsOnCurrentNetwork = getAccountsOnCurrentNetwork
self.getAccountsOnNetwork = getAccountsOnNetwork
self.accountsOnCurrentNetwork = accountsOnCurrentNetwork
Expand All @@ -53,6 +56,7 @@ public struct AccountsClient: Sendable {

extension AccountsClient {
public typealias GetCurrentNetworkID = @Sendable () async -> NetworkID
public typealias NextAccountIndex = @Sendable (NetworkID?) async -> HD.Path.Component.Child.Value
public typealias GetAccountsOnCurrentNetwork = @Sendable () async throws -> Profile.Network.Accounts
public typealias GetAccountsOnNetwork = @Sendable (NetworkID) async throws -> Profile.Network.Accounts

Expand Down Expand Up @@ -83,9 +87,7 @@ public struct NewAccountRequest: Sendable, Hashable {
// MARK: - SaveAccountRequest
public struct SaveAccountRequest: Sendable, Hashable {
public let account: Profile.Network.Account
public let shouldUpdateFactorSourceNextDerivationIndex: Bool
public init(account: Profile.Network.Account, shouldUpdateFactorSourceNextDerivationIndex: Bool) {
public init(account: Profile.Network.Account) {
self.account = account
self.shouldUpdateFactorSourceNextDerivationIndex = shouldUpdateFactorSourceNextDerivationIndex
}
}
2 changes: 2 additions & 0 deletions Sources/Clients/AccountsClient/AccountsClient+Test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extension DependencyValues {
extension AccountsClient: TestDependencyKey {
public static let noop = Self(
getCurrentNetworkID: { .kisharnet },
nextAccountIndex: { _ in 0 },
getAccountsOnCurrentNetwork: { throw NoopError() },
accountsOnCurrentNetwork: { AsyncLazySequence([]).eraseToAnyAsyncSequence() },
getAccountsOnNetwork: { _ in throw NoopError() },
Expand All @@ -23,6 +24,7 @@ extension AccountsClient: TestDependencyKey {
public static let previewValue: Self = .noop
public static let testValue = Self(
getCurrentNetworkID: unimplemented("\(Self.self).getCurrentNetworkID"),
nextAccountIndex: unimplemented("\(Self.self).nextAccountIndex"),
getAccountsOnCurrentNetwork: unimplemented("\(Self.self).getAccountsOnCurrentNetwork"),
accountsOnCurrentNetwork: unimplemented("\(Self.self).accountsOnCurrentNetwork"),
getAccountsOnNetwork: unimplemented("\(Self.self).getAccountsOnNetwork"),
Expand Down
23 changes: 18 additions & 5 deletions Sources/Clients/AccountsClientLive/AccountsClient+Live.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,41 @@ extension AccountsClient: DependencyKey {
) -> Self {
let saveVirtualAccount: SaveVirtualAccount = { request in
try await getProfileStore().updating {
try $0.addAccount(request.account, shouldUpdateFactorSourceNextDerivationIndex: request.shouldUpdateFactorSourceNextDerivationIndex)
try $0.addAccount(request.account)
}
}

let getAccountsOnCurrentNetwork: GetAccountsOnCurrentNetwork = {
try await getProfileStore().network().accounts
}

let getCurrentNetworkID: GetCurrentNetworkID = { await getProfileStore().profile.networkID }

let getAccountsOnNetwork: GetAccountsOnNetwork = { try await getProfileStore().profile.network(id: $0).accounts }

let nextAccountIndex: NextAccountIndex = { maybeNetworkID in
let currentNetworkID = await getCurrentNetworkID()
let networkID = maybeNetworkID ?? currentNetworkID
let index = await (try? getAccountsOnNetwork(networkID).count) ?? 0
return HD.Path.Component.Child.Value(index)
}

return Self(
getCurrentNetworkID: { await getProfileStore().profile.networkID },
getCurrentNetworkID: getCurrentNetworkID,
nextAccountIndex: nextAccountIndex,
getAccountsOnCurrentNetwork: getAccountsOnCurrentNetwork,
accountsOnCurrentNetwork: { await getProfileStore().accountValues() },
getAccountsOnNetwork: { try await getProfileStore().profile.network(id: $0).accounts },
getAccountsOnNetwork: getAccountsOnNetwork,
newVirtualAccount: { request in
let networkID = request.networkID
let profile = await getProfileStore().profile
let numberOfExistingAccounts = (try? profile.network(id: networkID))?.accounts.count ?? 0
let numberOfExistingAccounts = await nextAccountIndex(networkID)
return try Profile.Network.Account(
networkID: networkID,
index: .init(numberOfExistingAccounts),
factorInstance: request.factorInstance,
displayName: request.name,
extraProperties: .init(numberOfAccountsOnNetwork: numberOfExistingAccounts)
extraProperties: .init(numberOfAccountsOnNetwork: .init(numberOfExistingAccounts))
)
},
saveVirtualAccount: saveVirtualAccount,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public struct DappInteractionClient: Sendable {
}

extension DappInteractionClient {
public typealias AddWalletInteraction = @Sendable (P2P.Dapp.Request.Items) -> Void
public typealias AddWalletInteraction = @Sendable (P2P.Dapp.Request.Items) async -> Void
public typealias CompleteInteraction = @Sendable (P2P.RTCOutgoingMessage) async throws -> Void
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ extension DappInteractionClient: DependencyKey {
return .init(
interactions: interactionsStream.share().eraseToAnyAsyncSequence(),
addWalletInteraction: { items in
let request = ValidatedDappRequest.valid(.init(
@Dependency(\.gatewaysClient) var gatewaysClient

let request = await ValidatedDappRequest.valid(.init(
route: .wallet,
request: .init(
id: .init(UUID().uuidString),
items: items,
metadata: .init(
version: P2P.Dapp.currentVersion,
networkId: .default,
networkId: gatewaysClient.getCurrentNetworkID(),
origin: DappOrigin.wallet,
dAppDefinitionAddress: .wallet
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ extension DeviceFactorSourceClient: DependencyKey {

do {
let deviceFactorSource = try await factorSourcesClient.getFactorSources().babylonDeviceFactorSources().sorted(by: \.lastUsedOn).first
let accounts = try await accountsClient.getAccountsOnNetwork(NetworkID.default)

let accounts = try await accountsClient.getAccountsOnCurrentNetwork()

guard let deviceFactorSource,
let mnemonicWithPassphrase = try await secureStorageClient.loadMnemonicByFactorSourceID(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ extension ImportLegacyWalletClient: DependencyKey {
) async throws -> (accounts: NonEmpty<OrderedSet<MigratedAccount>>, networkID: NetworkID) {
let sortedOlympia = accounts.sorted(by: \.addressIndex)
let networkID = await factorSourcesClient.getCurrentNetworkID()
let accountIndexOffset = try await accountsClient.getAccountsOnCurrentNetwork().count
let accountIndexBase = await accountsClient.nextAccountIndex(networkID)

var accountOffset: HD.Path.Component.Child.Value = 0
guard let defaultAccountName: NonEmptyString = .init(rawValue: L10n.ImportOlympiaAccounts.AccountsToImport.unnamed) else {
// The L10n string should not be empty, so this should not be possible
struct ImplementationError: Error {}
Expand All @@ -29,6 +30,8 @@ extension ImportLegacyWalletClient: DependencyKey {

var accountsSet = OrderedSet<MigratedAccount>()
for olympiaAccount in sortedOlympia {
defer { accountOffset += 1 }
let accountIndex = accountIndexBase + accountOffset
let publicKey = SLIP10.PublicKey.ecdsaSecp256k1(olympiaAccount.publicKey)
let factorInstance = HierarchicalDeterministicFactorInstance(
id: factorSouceID,
Expand All @@ -37,13 +40,13 @@ extension ImportLegacyWalletClient: DependencyKey {
)

let displayName = olympiaAccount.displayName ?? defaultAccountName
let accountIndex = accountIndexOffset + Int(olympiaAccount.addressIndex)

let babylon = try Profile.Network.Account(
networkID: networkID,
index: HD.Path.Component.Child.Value(accountIndex),
factorInstance: factorInstance,
displayName: displayName,
extraProperties: .init(appearanceID: .fromIndex(accountIndex))
extraProperties: .init(appearanceID: .fromIndex(.init(accountIndex)))
)

let migrated = MigratedAccount(olympia: olympiaAccount, babylon: babylon)
Expand All @@ -57,8 +60,7 @@ extension ImportLegacyWalletClient: DependencyKey {
// Save all accounts
for account in accounts {
try await accountsClient.saveVirtualAccount(.init(
account: account.babylon,
shouldUpdateFactorSourceNextDerivationIndex: false
account: account.babylon
))
}

Expand Down
10 changes: 10 additions & 0 deletions Sources/Clients/PersonasClient/PersonasClient+Interface.swift
Original file line number Diff line number Diff line change
@@ -1,34 +1,44 @@
import ClientPrelude
import Cryptography
import EngineKit
import Profile

// MARK: - PersonasClient
public struct PersonasClient: Sendable {
public var nextPersonaIndex: NextPersonaIndex

public var personas: Personas
public var getPersonas: GetPersonas
public var getPersonasOnNetwork: GetPersonasOnNetwork
public var updatePersona: UpdatePersona

public var saveVirtualPersona: SaveVirtualPersona
public var hasAnyPersonaOnAnyNetwork: HasAnyPersonaOnAnyNetworks

public init(
personas: @escaping Personas,
nextPersonaIndex: @escaping NextPersonaIndex,
getPersonas: @escaping GetPersonas,
getPersonasOnNetwork: @escaping GetPersonasOnNetwork,
updatePersona: @escaping UpdatePersona,
saveVirtualPersona: @escaping SaveVirtualPersona,
hasAnyPersonaOnAnyNetwork: @escaping HasAnyPersonaOnAnyNetworks
) {
self.personas = personas
self.nextPersonaIndex = nextPersonaIndex
self.getPersonas = getPersonas
self.getPersonasOnNetwork = getPersonasOnNetwork
self.updatePersona = updatePersona
self.saveVirtualPersona = saveVirtualPersona
self.hasAnyPersonaOnAnyNetwork = hasAnyPersonaOnAnyNetwork
}
}

extension PersonasClient {
public typealias NextPersonaIndex = @Sendable (NetworkID?) async -> HD.Path.Component.Child.Value
public typealias Personas = @Sendable () async -> AnyAsyncSequence<Profile.Network.Personas>
public typealias GetPersonas = @Sendable () async throws -> Profile.Network.Personas
public typealias GetPersonasOnNetwork = @Sendable (NetworkID) async -> Profile.Network.Personas
public typealias HasAnyPersonaOnAnyNetworks = @Sendable () async -> Bool
public typealias UpdatePersona = @Sendable (Profile.Network.Persona) async throws -> Void
public typealias SaveVirtualPersona = @Sendable (Profile.Network.Persona) async throws -> Void
Expand Down
4 changes: 4 additions & 0 deletions Sources/Clients/PersonasClient/PersonasClient+Test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,18 @@ extension PersonasClient: TestDependencyKey {
public static let previewValue: Self = .noop
public static let testValue = Self(
personas: unimplemented("\(Self.self).personas"),
nextPersonaIndex: unimplemented("\(Self.self).nextPersonaIndex"),
getPersonas: unimplemented("\(Self.self).getPersonas"),
getPersonasOnNetwork: unimplemented("\(Self.self).getPersonasOnNetwork"),
updatePersona: unimplemented("\(Self.self).updatePersona"),
saveVirtualPersona: unimplemented("\(Self.self).saveVirtualPersona"),
hasAnyPersonaOnAnyNetwork: unimplemented("\(Self.self).hasAnyPersonaOnAnyNetwork")
)
public static let noop = Self(
personas: { AsyncLazySequence([]).eraseToAnyAsyncSequence() },
nextPersonaIndex: { _ in 0 },
getPersonas: { .init() },
getPersonasOnNetwork: { _ in .init() },
updatePersona: { _ in throw NoopError() },
saveVirtualPersona: { _ in },
hasAnyPersonaOnAnyNetwork: { true }
Expand Down
16 changes: 15 additions & 1 deletion Sources/Clients/PersonasClientLive/PersonasClient+Live.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import ClientPrelude
import Cryptography
import PersonasClient
import ProfileStore

Expand All @@ -8,16 +9,29 @@ extension PersonasClient: DependencyKey {
public static func live(
profileStore getProfileStore: @escaping @Sendable () async -> ProfileStore = { await .shared }
) -> Self {
Self(
let getPersonasOnNetwork: GetPersonasOnNetwork = { networkID in
guard let network = try? await getProfileStore().profile.network(id: networkID) else {
return .init()
}
return network.personas
}

return Self(
personas: {
await getProfileStore().personaValues()
},
nextPersonaIndex: { maybeNextworkID async -> HD.Path.Component.Child.Value in
let currentNetworkID = await getProfileStore().profile.networkID
let networkID = maybeNextworkID ?? currentNetworkID
return await HD.Path.Component.Child.Value(getPersonasOnNetwork(networkID).count)
},
getPersonas: {
guard let network = await getProfileStore().network else {
return .init()
}
return network.personas
},
getPersonasOnNetwork: getPersonasOnNetwork,
updatePersona: { persona in
try await getProfileStore().updating {
try $0.updatePersona(persona)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import Prelude
#if DEBUG

extension TransactionManifest {
public static let previewValue = try! TransactionManifest(instructions: .fromString(string: complexManifestString, networkId: NetworkID.default.rawValue), blobs: [])
public static let previewValue = try! TransactionManifest(instructions: .fromString(string: complexManifestString, networkId: Radix.Gateway.default.network.id.rawValue), blobs: [])
}

private let complexManifestString = """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extension Profile.Network.Account {
validatingAddress: "account_sim1cyvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cve475w0q"
),
securityState: .unsecured(.init(
entityIndex: 0,
transactionSigning: .init(
factorSourceID: .device(hash: "09bfa80bcc9b75d6ad82d59730f7b179cbc668ba6ad4008721d5e6a179ff55f1"),
publicKey: .eddsaEd25519(.init(
Expand All @@ -28,14 +29,16 @@ extension Profile.Network.Account {
validatingAddress: "account_sim1cyvgx33089ukm2pl97pv4max0x40ruvfy4lt60yvya744cve475w0q"
),
securityState: .unsecured(.init(
entityIndex: 1,
transactionSigning: .init(
factorSourceID: .device(hash: "09bfa80bcc9b75d6ad82d59730f7b179cbc668ba6ad4008721d5e6a179ff55f1"),
publicKey: .eddsaEd25519(.init(
compressedRepresentation: Data(
hex: "b862c4ef84a4a97c37760636f6b94d1fba7b4881ac15a073f6c57e2996bbeca8")
)),
derivationPath: .accountPath(.init(derivationPath: "m/44H/1022H/10H/525H/1460H/1H"))
))),
)
)),
appearanceID: ._1,
displayName: "Secondary"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extension Profile.Network.Persona {
validatingAddress: "identity_tdx_21_12tljxea3s0mse52jmpvsphr0haqs86sung8d3qlhr763nxttj59650"
),
securityState: .unsecured(.init(
entityIndex: 0,
transactionSigning: .init(
factorSourceID: .device(hash: "09bfa80bcc9b75d6ad82d59730f7b179cbc668ba6ad4008721d5e6a179ff55f1"),
publicKey: .eddsaEd25519(.init(
Expand All @@ -28,6 +29,7 @@ extension Profile.Network.Persona {
validatingAddress: "identity_tdx_21_12tljxea3s0mse52jmpvsphr0haqs86sung8d3qlhr763nxttj59650"
),
securityState: .unsecured(.init(
entityIndex: 0,
transactionSigning: .init(
factorSourceID: .device(hash: "09bfa80bcc9b75d6ad82d59730f7b179cbc668ba6ad4008721d5e6a179ff55f1"),
publicKey: .eddsaEd25519(.init(
Expand Down
Loading