diff --git a/Sources/KukaiCoreSwift/Models/WalletMetadata.swift b/Sources/KukaiCoreSwift/Models/WalletMetadata.swift index 370439d..edfe6ae 100644 --- a/Sources/KukaiCoreSwift/Models/WalletMetadata.swift +++ b/Sources/KukaiCoreSwift/Models/WalletMetadata.swift @@ -265,6 +265,7 @@ public class WalletMetadataList: Codable, Hashable { /// Object to store UI related info about wallets, seperated from the wallet object itself to avoid issues merging together public class WalletMetadata: Codable, Hashable { public var address: String + public var derivationPath: String? public var hdWalletGroupName: String? public var walletNickname: String? public var socialUsername: String? @@ -278,7 +279,6 @@ public class WalletMetadata: Codable, Hashable { public var isWatchOnly: Bool public var bas58EncodedPublicKey: String public var backedUp: Bool - public var customDerivationPath: String? public func hasMainnetDomain() -> Bool { return (mainnetDomains ?? []).count > 0 @@ -320,13 +320,9 @@ public class WalletMetadata: Codable, Hashable { } } - public func childCountExcludingCustomDerivationPaths() -> Int { - let excluded = children.filter { $0.customDerivationPath == nil } - return excluded.count - } - - public init(address: String, hdWalletGroupName: String?, walletNickname: String? = nil, socialUsername: String? = nil, socialUserId: String? = nil, mainnetDomains: [TezosDomainsReverseRecord]? = nil, ghostnetDomains: [TezosDomainsReverseRecord]? = nil, socialType: TorusAuthProvider? = nil, type: WalletType, children: [WalletMetadata], isChild: Bool, isWatchOnly: Bool, bas58EncodedPublicKey: String, backedUp: Bool, customDerivationPath: String?) { + public init(address: String, derivationPath: String?, hdWalletGroupName: String?, walletNickname: String? = nil, socialUsername: String? = nil, socialUserId: String? = nil, mainnetDomains: [TezosDomainsReverseRecord]? = nil, ghostnetDomains: [TezosDomainsReverseRecord]? = nil, socialType: TorusAuthProvider? = nil, type: WalletType, children: [WalletMetadata], isChild: Bool, isWatchOnly: Bool, bas58EncodedPublicKey: String, backedUp: Bool) { self.address = address + self.derivationPath = derivationPath self.hdWalletGroupName = hdWalletGroupName self.walletNickname = walletNickname self.socialUsername = socialUsername @@ -340,7 +336,6 @@ public class WalletMetadata: Codable, Hashable { self.isWatchOnly = isWatchOnly self.bas58EncodedPublicKey = bas58EncodedPublicKey self.backedUp = backedUp - self.customDerivationPath = customDerivationPath } public static func == (lhs: WalletMetadata, rhs: WalletMetadata) -> Bool { diff --git a/Sources/KukaiCoreSwift/Services/WalletCacheService.swift b/Sources/KukaiCoreSwift/Services/WalletCacheService.swift index 9b5b303..30887ea 100644 --- a/Sources/KukaiCoreSwift/Services/WalletCacheService.swift +++ b/Sources/KukaiCoreSwift/Services/WalletCacheService.swift @@ -85,7 +85,7 @@ public class WalletCacheService { - Parameter childOfIndex: An optional `Int` to denote the index of the HD wallet that this wallet is a child of - Returns: Bool, indicating if the storage was successful or not */ - public func cache(wallet: T, childOfIndex: Int?, backedUp: Bool, customDerivationPath: String? = nil) throws { + public func cache(wallet: T, childOfIndex: Int?, backedUp: Bool) throws { guard let existingWallets = readWalletsFromDiskAndDecrypt() else { Logger.walletCache.error("cache - Unable to cache wallet, as can't decrypt existing wallets") throw WalletCacheError.unableToDecrypt @@ -102,6 +102,13 @@ public class WalletCacheService { let newMetadata = readMetadataFromDiskAndDecrypt() var array = metadataArray(forType: wallet.type, fromMeta: newMetadata) + var path: String? = nil + if wallet.type == .hd, let w = wallet as? HDWallet { + path = w.derivationPath + } else if wallet.type == .ledger, let w = wallet as? LedgerWallet { + path = w.derivationPath + } + if let index = childOfIndex { // If child index is present, update the correct sub array to include this new item, checking forst that we have the correct details @@ -110,7 +117,7 @@ public class WalletCacheService { throw WalletCacheError.requestedIndexTooHigh } - array[index].children.append(WalletMetadata(address: wallet.address, hdWalletGroupName: nil, walletNickname: nil, socialUsername: nil, type: wallet.type, children: [], isChild: true, isWatchOnly: false, bas58EncodedPublicKey: wallet.publicKeyBase58encoded(), backedUp: backedUp, customDerivationPath: customDerivationPath)) + array[index].children.append(WalletMetadata(address: wallet.address, derivationPath: path, hdWalletGroupName: nil, walletNickname: nil, socialUsername: nil, type: wallet.type, children: [], isChild: true, isWatchOnly: false, bas58EncodedPublicKey: wallet.publicKeyBase58encoded(), backedUp: backedUp)) } else if wallet.type == .hd || wallet.type == .ledger { @@ -135,17 +142,17 @@ public class WalletCacheService { newNumber = array.count + 1 } - array.append(WalletMetadata(address: wallet.address, hdWalletGroupName: "\(groupNameStart)\(newNumber)", walletNickname: nil, socialUsername: nil, socialType: nil, type: wallet.type, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: wallet.publicKeyBase58encoded(), backedUp: backedUp, customDerivationPath: customDerivationPath)) + array.append(WalletMetadata(address: wallet.address, derivationPath: path, hdWalletGroupName: "\(groupNameStart)\(newNumber)", walletNickname: nil, socialUsername: nil, socialType: nil, type: wallet.type, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: wallet.publicKeyBase58encoded(), backedUp: backedUp)) } else if let torusWallet = wallet as? TorusWallet { // If social, cast and fetch special attributes - array.append(WalletMetadata(address: wallet.address, hdWalletGroupName: nil, walletNickname: nil, socialUsername: torusWallet.socialUsername, socialUserId: torusWallet.socialUserId, socialType: torusWallet.authProvider, type: wallet.type, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: wallet.publicKeyBase58encoded(), backedUp: backedUp, customDerivationPath: customDerivationPath)) + array.append(WalletMetadata(address: wallet.address, derivationPath: path, hdWalletGroupName: nil, walletNickname: nil, socialUsername: torusWallet.socialUsername, socialUserId: torusWallet.socialUserId, socialType: torusWallet.authProvider, type: wallet.type, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: wallet.publicKeyBase58encoded(), backedUp: backedUp)) } else { // Else, add basic wallet to the list its supposed to go to - array.append(WalletMetadata(address: wallet.address, hdWalletGroupName: nil, walletNickname: nil, socialUsername: nil, socialType: nil, type: wallet.type, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: wallet.publicKeyBase58encoded(), backedUp: backedUp, customDerivationPath: customDerivationPath)) + array.append(WalletMetadata(address: wallet.address, derivationPath: path, hdWalletGroupName: nil, walletNickname: nil, socialUsername: nil, socialType: nil, type: wallet.type, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: wallet.publicKeyBase58encoded(), backedUp: backedUp)) } // Update wallet metadata array, and then commit to disk diff --git a/Tests/KukaiCoreSwiftTests/Models/TzKTTransactionTests.swift b/Tests/KukaiCoreSwiftTests/Models/TzKTTransactionTests.swift index 98e9b31..2c2fd62 100644 --- a/Tests/KukaiCoreSwiftTests/Models/TzKTTransactionTests.swift +++ b/Tests/KukaiCoreSwiftTests/Models/TzKTTransactionTests.swift @@ -78,7 +78,7 @@ final class TzKTTransactionTests: XCTestCase { } func testPlaceholders() { - let source = WalletMetadata(address: "tz1abc", hdWalletGroupName: nil, type: .hd, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + let source = WalletMetadata(address: "tz1abc", derivationPath: nil, hdWalletGroupName: nil, type: .hd, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true) let placeholder1 = TzKTTransaction.placeholder(withStatus: .unconfirmed, id: 567, opHash: "abc123", type: .transaction, counter: 0, fromWallet: source, newDelegate: TzKTAddress(alias: "Baking Benjamins", address: "tz1YgDUQV2eXm8pUWNz3S5aWP86iFzNp4jnD")) let placeholder2 = TzKTTransaction.placeholder(withStatus: .unconfirmed, id: 456, opHash: "def456", type: .transaction, counter: 1, fromWallet: source, destination: TzKTAddress(alias: nil, address: "tz1def"), xtzAmount: .init(fromNormalisedAmount: 4.17, decimalPlaces: 6), parameters: nil, primaryToken: nil, baker: nil, kind: nil) diff --git a/Tests/KukaiCoreSwiftTests/Services/WalletCacheServiceTests.swift b/Tests/KukaiCoreSwiftTests/Services/WalletCacheServiceTests.swift index 5ee04a9..712d8d4 100644 --- a/Tests/KukaiCoreSwiftTests/Services/WalletCacheServiceTests.swift +++ b/Tests/KukaiCoreSwiftTests/Services/WalletCacheServiceTests.swift @@ -249,7 +249,7 @@ class WalletCacheServiceTests: XCTestCase { func testMetadata() { let mainentDomain = [TezosDomainsReverseRecord(id: "123", address: "tz1abc123", owner: "tz1abc123", expiresAtUtc: nil, domain: TezosDomainsDomain(name: "blah.tez", address: "tz1abc123"))] let ghostnetDomain = [TezosDomainsReverseRecord(id: "123", address: "tz1abc123", owner: "tz1abc123", expiresAtUtc: nil, domain: TezosDomainsDomain(name: "blah.gho", address: "tz1abc123"))] - let metadata1 = WalletMetadata(address: "tz1abc123", hdWalletGroupName: nil, mainnetDomains: mainentDomain, ghostnetDomains: ghostnetDomain, type: .hd, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + let metadata1 = WalletMetadata(address: "tz1abc123", derivationPath: nil, hdWalletGroupName: nil, mainnetDomains: mainentDomain, ghostnetDomains: ghostnetDomain, type: .hd, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true) XCTAssert(metadata1.hasMainnetDomain()) XCTAssert(metadata1.hasGhostnetDomain()) @@ -264,7 +264,7 @@ class WalletCacheServiceTests: XCTestCase { - let metadata2 = WalletMetadata(address: "tz1def456", hdWalletGroupName: nil, type: .hd, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + let metadata2 = WalletMetadata(address: "tz1def456", derivationPath: nil, hdWalletGroupName: nil, type: .hd, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true) XCTAssert(!metadata2.hasMainnetDomain()) XCTAssert(!metadata2.hasGhostnetDomain()) @@ -273,20 +273,20 @@ class WalletCacheServiceTests: XCTestCase { func testMetadataList() { let mainentDomain = TezosDomainsReverseRecord(id: "123", address: "tz1abc123", owner: "tz1abc123", expiresAtUtc: nil, domain: TezosDomainsDomain(name: "blah.tez", address: "tz1abc123")) let ghostnetDomain = TezosDomainsReverseRecord(id: "123", address: "tz1abc123", owner: "tz1abc123", expiresAtUtc: nil, domain: TezosDomainsDomain(name: "blah.gho", address: "tz1abc123")) - let child = WalletMetadata(address: "tz1child", hdWalletGroupName: nil, type: .hd, children: [], isChild: true, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) - let updatedWatch = WalletMetadata(address: "tz1jkl", hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "blah", backedUp: true, customDerivationPath: nil) + let child = WalletMetadata(address: "tz1child", derivationPath: nil, hdWalletGroupName: nil, type: .hd, children: [], isChild: true, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true) + let updatedWatch = WalletMetadata(address: "tz1jkl", derivationPath: nil, hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "blah", backedUp: true) let hd: [WalletMetadata] = [ - WalletMetadata(address: "tz1abc123", hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [child], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + WalletMetadata(address: "tz1abc123", derivationPath: nil, hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [child], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true) ] let social: [WalletMetadata] = [ - WalletMetadata(address: "tz1def", hdWalletGroupName: nil, socialUsername: "test@gmail.com", socialType: .google, type: .social, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + WalletMetadata(address: "tz1def", derivationPath: nil, hdWalletGroupName: nil, socialUsername: "test@gmail.com", socialType: .google, type: .social, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true) ] let linear: [WalletMetadata] = [ - WalletMetadata(address: "tz1ghi", hdWalletGroupName: nil, type: .regular, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + WalletMetadata(address: "tz1ghi", derivationPath: nil, hdWalletGroupName: nil, type: .regular, children: [], isChild: false, isWatchOnly: false, bas58EncodedPublicKey: "", backedUp: true) ] let watch: [WalletMetadata] = [ - WalletMetadata(address: "tz1jkl", hdWalletGroupName: nil, type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + WalletMetadata(address: "tz1jkl", derivationPath: nil, hdWalletGroupName: nil, type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "", backedUp: true) ] let list = WalletMetadataList(socialWallets: social, hdWallets: hd, linearWallets: linear, ledgerWallets: [], watchWallets: watch) @@ -333,7 +333,7 @@ class WalletCacheServiceTests: XCTestCase { func testWatchWallet() { XCTAssert(walletCacheService.deleteAllCacheAndKeys()) - let watchWallet = WalletMetadata(address: "tz1jkl", hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + let watchWallet = WalletMetadata(address: "tz1jkl", derivationPath: nil, hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "", backedUp: true) do { try walletCacheService.cacheWatchWallet(metadata: watchWallet) @@ -354,7 +354,7 @@ class WalletCacheServiceTests: XCTestCase { XCTFail("Should not error: \(error)") } - let watchWallet = WalletMetadata(address: MockConstants.defaultLinearWallet.address, hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + let watchWallet = WalletMetadata(address: MockConstants.defaultLinearWallet.address, derivationPath: nil, hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "", backedUp: true) do { try walletCacheService.cacheWatchWallet(metadata: watchWallet) @@ -368,7 +368,7 @@ class WalletCacheServiceTests: XCTestCase { XCTAssert(walletCacheService.deleteAllCacheAndKeys()) // Add watch and confirm - let watchWallet = WalletMetadata(address: MockConstants.defaultLinearWallet.address, hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "", backedUp: true, customDerivationPath: nil) + let watchWallet = WalletMetadata(address: MockConstants.defaultLinearWallet.address, derivationPath: nil, hdWalletGroupName: nil, mainnetDomains: [], ghostnetDomains: [], type: .hd, children: [], isChild: false, isWatchOnly: true, bas58EncodedPublicKey: "", backedUp: true) do { try walletCacheService.cacheWatchWallet(metadata: watchWallet) @@ -403,14 +403,13 @@ class WalletCacheServiceTests: XCTestCase { try walletCacheService.cache(wallet: ledgerWallet, childOfIndex: nil, backedUp: true) try walletCacheService.cache(wallet: ledgerWalletChild1, childOfIndex: 0, backedUp: true) try walletCacheService.cache(wallet: ledgerWalletChild2, childOfIndex: 0, backedUp: true) - try walletCacheService.cache(wallet: ledgerWalletChild3, childOfIndex: 0, backedUp: true, customDerivationPath: ledgerWalletChild3.derivationPath) + try walletCacheService.cache(wallet: ledgerWalletChild3, childOfIndex: 0, backedUp: true) let list1 = walletCacheService.readMetadataFromDiskAndDecrypt() let ledgers1 = list1.ledgerWallets - let excludedCount = ledgers1[0].childCountExcludingCustomDerivationPaths() XCTAssert(ledgers1.count == 1, ledgers1.count.description) XCTAssert(ledgers1[0].children.count == 3, ledgers1[0].children.count.description) - XCTAssert(excludedCount == 2, excludedCount.description) + XCTAssert(ledgers1[0].children.last?.derivationPath == "m/44'/1729'/147'/62'", ledgers1[0].children.last?.derivationPath ?? "-") let _ = WalletCacheService().deleteWallet(withAddress: "tz1abc", parentIndex: nil)