From c03047031b759f25b80f04acaf6c6f6c7512874a Mon Sep 17 00:00:00 2001 From: Radmir Date: Thu, 26 Feb 2026 14:29:49 +0500 Subject: [PATCH 1/2] Add Bitcoin WIF private key import support (#1738) Add base58 encoding support for UTXO chains (Bitcoin, Litecoin, Doge, BitcoinCash) and handle WIF format (37/38 byte decoded output) in private key decoding. --- .../Keystore/Sources/Extensions/Chain+Keystore.swift | 2 ++ Packages/Keystore/Sources/Store/WalletKeyStore.swift | 10 ++++++++-- Packages/Keystore/Tests/WalletKeyStoreTests.swift | 11 +++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Packages/Keystore/Sources/Extensions/Chain+Keystore.swift b/Packages/Keystore/Sources/Extensions/Chain+Keystore.swift index 41353863c..3404cc9ed 100644 --- a/Packages/Keystore/Sources/Extensions/Chain+Keystore.swift +++ b/Packages/Keystore/Sources/Extensions/Chain+Keystore.swift @@ -15,6 +15,8 @@ public extension Chain { switch self { case .solana: [.base58, .hex] + case .bitcoin, .litecoin, .doge, .bitcoinCash: + [.base58, .hex] case .stellar: [.base32, .hex] default: diff --git a/Packages/Keystore/Sources/Store/WalletKeyStore.swift b/Packages/Keystore/Sources/Store/WalletKeyStore.swift index b69cbecb3..6172ddb83 100644 --- a/Packages/Keystore/Sources/Store/WalletKeyStore.swift +++ b/Packages/Keystore/Sources/Store/WalletKeyStore.swift @@ -48,8 +48,14 @@ struct WalletKeyStore: Sendable { } switch encoding { case .base58: - if let decoded = Base58.decodeNoCheck(string: key), decoded.count % 32 == 0 { - data = decoded.prefix(32) + if let decoded = Base58.decodeNoCheck(string: key) { + if decoded.count % 32 == 0 { + data = Data(decoded.prefix(32)) + } else if decoded.count == 37 || decoded.count == 38 { + // WIF format: [1 version] + [32 key] + [4 checksum] (37 bytes, uncompressed) + // or [1 version] + [32 key] + [1 compression flag] + [4 checksum] (38 bytes, compressed) + data = Data(decoded[1..<33]) + } } case .hex: data = Data(hexString: key) diff --git a/Packages/Keystore/Tests/WalletKeyStoreTests.swift b/Packages/Keystore/Tests/WalletKeyStoreTests.swift index 86c0d5a73..c67ca2d1b 100644 --- a/Packages/Keystore/Tests/WalletKeyStoreTests.swift +++ b/Packages/Keystore/Tests/WalletKeyStoreTests.swift @@ -81,6 +81,17 @@ final class WalletKeyStoreTests { #expect(address == "GADB4BDKTOE36L6QN2JLIPNNJ7EZPSY5BIVKWXLWYZLIPXNQWIRQQZKT") } + @Test func importBitcoinWIF() throws { + let hex = "0x0000000000000000000000000000000000000000000000000000000000000001" + let wif = "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" + + let keyFromHex = try WalletKeyStore.decodeKey(hex, chain: .bitcoin) + let keyFromWIF = try WalletKeyStore.decodeKey(wif, chain: .bitcoin) + + #expect(keyFromWIF.data == keyFromHex.data) + #expect(CoinType.bitcoin.deriveAddress(privateKey: keyFromWIF) == "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") + } + @Test func addImportWallet() async throws { let store = WalletKeyStore.mock() let newWallet = try store.importWallet( From 679b452a4336684cd7e27b8c42a7a25ce064f351 Mon Sep 17 00:00:00 2001 From: gemcoder21 <104884878+gemcoder21@users.noreply.github.com> Date: Fri, 27 Feb 2026 02:24:10 +0000 Subject: [PATCH 2/2] Refactor keystore private key encoding & import flow Rename and centralize private-key encoding APIs and adjust import flows. - Replace getPrivateKey(..., encoding:) with getPrivateKeyEncoded(...) across service, protocol, local keystore and mocks. - Remove per-chain EncodingType enum and Chain+Keystore extension; delegate encoding/decoding to GemstonePrimitives (decodePrivateKey / supportsPrivateKeyImport / Base58 handling moved). - Simplify LocalKeystore to return encoded private key based on chain type and zeroize raw bytes. - Move private-key decoding logic in WalletKeyStore to use GemstonePrimitives decode function and simplify validation. - Update ImportWallet flow to async completion handlers, add support check for private key import per-chain, present errors via alert, and adjust navigation handling. - Update Package.swift for Keystore to add GemstonePrimitives dependency and adjust targets; remove obsolete Package.resolved and deleted tests relying on removed encoding types. - Update tests to use the new encoded API and remove outdated WIF/encoding unit tests. - Bump core submodule commit. These changes centralize encoding logic, remove duplicated encoding types, and modernize async import handling and error reporting. --- .../ViewModels/WalletIDetailViewModel.swift | 6 +- .../ImportWalletNavigationStack.swift | 17 +++--- .../ImportWalletSceneViewModel.swift | 26 +++++---- .../WalletService/WalletService.swift | 4 +- Packages/Keystore/Package.resolved | 15 ----- Packages/Keystore/Package.swift | 6 +- .../Sources/Extensions/Chain+Keystore.swift | 26 --------- Packages/Keystore/Sources/LocalKeystore.swift | 11 ++-- .../Keystore/Sources/Protocols/Keystore.swift | 2 +- .../Sources/Store/WalletKeyStore.swift | 58 ++----------------- Packages/Keystore/TestKit/KeystoreMock.swift | 2 +- .../Keystore/Tests/Chain+KeystoreTests.swift | 15 ----- .../Keystore/Tests/LocalKeystoreTests.swift | 22 ++----- .../Keystore/Tests/WalletKeyStoreTests.swift | 10 ---- .../Primitives/Sources/EncodingType.swift | 11 ---- core | 2 +- 16 files changed, 47 insertions(+), 186 deletions(-) delete mode 100644 Packages/Keystore/Package.resolved delete mode 100644 Packages/Keystore/Sources/Extensions/Chain+Keystore.swift delete mode 100644 Packages/Keystore/Tests/Chain+KeystoreTests.swift delete mode 100644 Packages/Primitives/Sources/EncodingType.swift diff --git a/Features/ManageWallets/Sources/ViewModels/WalletIDetailViewModel.swift b/Features/ManageWallets/Sources/ViewModels/WalletIDetailViewModel.swift index a4d718c82..65c69f36e 100644 --- a/Features/ManageWallets/Sources/ViewModels/WalletIDetailViewModel.swift +++ b/Features/ManageWallets/Sources/ViewModels/WalletIDetailViewModel.swift @@ -96,11 +96,7 @@ extension WalletDetailViewModel { func getPrivateKey() async throws -> String { let chain = wallet.accounts[0].chain - return try await walletService.getPrivateKey( - wallet: wallet, - chain: chain, - encoding: chain.defaultKeyEncodingType - ) + return try await walletService.getPrivateKeyEncoded(wallet: wallet, chain: chain) } func delete() async throws { diff --git a/Features/Onboarding/Sources/Navigation/ImportWalletNavigationStack.swift b/Features/Onboarding/Sources/Navigation/ImportWalletNavigationStack.swift index 80b7d2d42..1e0064ab1 100644 --- a/Features/Onboarding/Sources/Navigation/ImportWalletNavigationStack.swift +++ b/Features/Onboarding/Sources/Navigation/ImportWalletNavigationStack.swift @@ -3,11 +3,13 @@ import SwiftUI import Primitives import Localization +import Components import PrimitivesComponents public struct ImportWalletNavigationStack: View { @State private var model: ImportWalletViewModel @State private var navigationPath = NavigationPath() + @State private var isPresentingAlertMessage: AlertMessage? public init(model: ImportWalletViewModel) { _model = State(initialValue: model) @@ -56,6 +58,7 @@ public struct ImportWalletNavigationStack: View { } } } + .alertSheet($isPresentingAlertMessage) } @ViewBuilder @@ -82,14 +85,12 @@ extension ImportWalletNavigationStack { } } - func onImportComplete(data: WalletImportData) { - Task { - do { - let wallet = try await model.importWallet(data: data) - navigate(to: .walletProfile(wallet: wallet)) - } catch { - debugLog("Failed to import wallet: \(error)") - } + func onImportComplete(data: WalletImportData) async { + do { + let wallet = try await model.importWallet(data: data) + navigate(to: .walletProfile(wallet: wallet)) + } catch { + isPresentingAlertMessage = AlertMessage(message: error.localizedDescription) } } diff --git a/Features/Onboarding/Sources/ViewModels/ImportWalletSceneViewModel.swift b/Features/Onboarding/Sources/ViewModels/ImportWalletSceneViewModel.swift index d74637cf1..7ae6016f2 100644 --- a/Features/Onboarding/Sources/ViewModels/ImportWalletSceneViewModel.swift +++ b/Features/Onboarding/Sources/ViewModels/ImportWalletSceneViewModel.swift @@ -8,6 +8,7 @@ import PrimitivesComponents import SwiftUI import Components import GemstonePrimitives +internal import func Gemstone.supportsPrivateKeyImport import enum Keystore.KeystoreImportType import struct Keystore.Mnemonic @@ -29,13 +30,13 @@ final class ImportWalletSceneViewModel { var isPresentingScanner = false var isPresentingAlertMessage: AlertMessage? - private let onComplete: ((WalletImportData) -> Void)? + private let onComplete: ((WalletImportData) async -> Void)? init( walletService: WalletService, nameService: any NameServiceable, type: ImportWalletType, - onComplete: ((WalletImportData) -> Void)? + onComplete: ((WalletImportData) async -> Void)? ) { self.walletService = walletService self.nameService = nameService @@ -73,11 +74,11 @@ final class ImportWalletSceneViewModel { switch type { case .multicoin: return [.phrase] - case .chain: - if chain?.keyEncodingTypes.isEmpty ?? true { - return [.phrase, .address] + case .chain(let chain): + if supportsPrivateKeyImport(chain: chain.rawValue) { + return [.phrase, .privateKey, .address] } - return [.phrase, .privateKey, .address] + return [.phrase, .address] } } @@ -175,12 +176,12 @@ extension ImportWalletSceneViewModel { } switch type { case .multicoin: - importWallet( + await importWallet( name: recipient.name, keystoreType: .phrase(words: words, chains: AssetConfiguration.allChains) ) case .chain(let chain): - importWallet( + await importWallet( name: recipient.name, keystoreType: .single(words: words, chain: chain) ) @@ -189,7 +190,7 @@ extension ImportWalletSceneViewModel { guard try validateForm(type: importType, address: recipient.address, words: [trimmedInput]) else { return } - importWallet(name: recipient.name, keystoreType: .privateKey(text: trimmedInput, chain: chain!)) + await importWallet(name: recipient.name, keystoreType: .privateKey(text: trimmedInput, chain: chain!)) case .address: guard try validateForm(type: importType, address: recipient.address, words: []) else { return @@ -197,12 +198,13 @@ extension ImportWalletSceneViewModel { let chain = chain! let address = chain.checksumAddress(recipient.address) - importWallet(name: recipient.name, keystoreType: .address(address: address, chain: chain)) + await importWallet(name: recipient.name, keystoreType: .address(address: address, chain: chain)) } } - private func importWallet(name: String, keystoreType: KeystoreImportType) { - onComplete?(WalletImportData(name: name, keystoreType: keystoreType)) + private func importWallet(name: String, keystoreType: KeystoreImportType) async { + await onComplete?(WalletImportData(name: name, keystoreType: keystoreType)) + buttonState = .normal } private func validateForm(type: WalletImportType, address: String, words: [String]) throws -> Bool { diff --git a/Packages/FeatureServices/WalletService/WalletService.swift b/Packages/FeatureServices/WalletService/WalletService.swift index cf0a45b4e..0630f4655 100644 --- a/Packages/FeatureServices/WalletService/WalletService.swift +++ b/Packages/FeatureServices/WalletService/WalletService.swift @@ -145,7 +145,7 @@ public struct WalletService: Sendable { try await keystore.getMnemonic(wallet: wallet) } - public func getPrivateKey(wallet: Primitives.Wallet, chain: Chain, encoding: EncodingType) async throws -> String { - try await keystore.getPrivateKey(wallet: wallet, chain: chain, encoding: encoding) + public func getPrivateKeyEncoded(wallet: Primitives.Wallet, chain: Chain) async throws -> String { + try await keystore.getPrivateKeyEncoded(wallet: wallet, chain: chain) } } diff --git a/Packages/Keystore/Package.resolved b/Packages/Keystore/Package.resolved deleted file mode 100644 index 6d8bde1fb..000000000 --- a/Packages/Keystore/Package.resolved +++ /dev/null @@ -1,15 +0,0 @@ -{ - "originHash" : "6a214e7c1717bde07d22f26ce45795884958bb64b342b7bbfe1e5253a517350f", - "pins" : [ - { - "identity" : "bigint", - "kind" : "remoteSourceControl", - "location" : "https://github.com/gemwalletcom/BigInt.git", - "state" : { - "revision" : "e07e00fa1fd435143a2dcf8b7eec9a7710b2fdfe", - "version" : "5.7.0" - } - } - ], - "version" : 3 -} diff --git a/Packages/Keystore/Package.swift b/Packages/Keystore/Package.swift index 1d24b0945..3ade00414 100644 --- a/Packages/Keystore/Package.swift +++ b/Packages/Keystore/Package.swift @@ -17,7 +17,8 @@ let package = Package( .package(name: "Primitives", path: "../Primitives"), .package(name: "Formatters", path: "../Formatters"), .package(name: "WalletCore", path: "../WalletCore"), - .package(name: "Keychain", path: "../Keychain") + .package(name: "Keychain", path: "../Keychain"), + .package(name: "GemstonePrimitives", path: "../GemstonePrimitives"), ], targets: [ .target( @@ -27,7 +28,8 @@ let package = Package( .product(name: "WalletCorePrimitives", package: "WalletCore"), "Primitives", "Formatters", - "Keychain" + "Keychain", + "GemstonePrimitives", ], path: "Sources" ), diff --git a/Packages/Keystore/Sources/Extensions/Chain+Keystore.swift b/Packages/Keystore/Sources/Extensions/Chain+Keystore.swift deleted file mode 100644 index 3404cc9ed..000000000 --- a/Packages/Keystore/Sources/Extensions/Chain+Keystore.swift +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright (c). Gem Wallet. All rights reserved. - -import Foundation -import Primitives -import WalletCore - -public extension Chain { - - var defaultKeyEncodingType: EncodingType { - keyEncodingTypes.first! - } - - var keyEncodingTypes: [EncodingType] { - //TODO: Use chain type in the future - switch self { - case .solana: - [.base58, .hex] - case .bitcoin, .litecoin, .doge, .bitcoinCash: - [.base58, .hex] - case .stellar: - [.base32, .hex] - default: - [.hex] - } - } -} diff --git a/Packages/Keystore/Sources/LocalKeystore.swift b/Packages/Keystore/Sources/LocalKeystore.swift index 621495f12..77a692e15 100644 --- a/Packages/Keystore/Sources/LocalKeystore.swift +++ b/Packages/Keystore/Sources/LocalKeystore.swift @@ -1,4 +1,5 @@ import Foundation +import GemstonePrimitives import Primitives import WalletCore @@ -112,16 +113,14 @@ public final class LocalKeystore: Keystore, @unchecked Sendable { } } - public func getPrivateKey(wallet: Primitives.Wallet, chain: Chain, encoding: EncodingType) async throws -> String { + public func getPrivateKeyEncoded(wallet: Primitives.Wallet, chain: Chain) async throws -> String { var data = try await getPrivateKey(wallet: wallet, chain: chain) defer { data.zeroize() } - switch encoding { - case .base58: + switch chain.type { + case .bitcoin, .solana: return Base58.encodeNoCheck(data: data) - case .hex: + default: return data.hexString.append0x - case .base32: - throw KeystoreError.invalidPrivateKeyEncoding } } diff --git a/Packages/Keystore/Sources/Protocols/Keystore.swift b/Packages/Keystore/Sources/Protocols/Keystore.swift index 8870c926b..a49355613 100644 --- a/Packages/Keystore/Sources/Protocols/Keystore.swift +++ b/Packages/Keystore/Sources/Protocols/Keystore.swift @@ -12,7 +12,7 @@ public protocol Keystore: Sendable { func setupChains(chains: [Chain], for wallets: [Wallet]) throws -> [Wallet] func deleteKey(for wallet: Wallet) async throws func getPrivateKey(wallet: Wallet, chain: Chain) async throws -> Data - func getPrivateKey(wallet: Wallet, chain: Chain, encoding: EncodingType) async throws -> String + func getPrivateKeyEncoded(wallet: Wallet, chain: Chain) async throws -> String func getMnemonic(wallet: Wallet) async throws -> [String] func getPasswordAuthentication() throws -> KeystoreAuthentication func sign(hash: Data, wallet: Wallet, chain: Chain) async throws -> Data diff --git a/Packages/Keystore/Sources/Store/WalletKeyStore.swift b/Packages/Keystore/Sources/Store/WalletKeyStore.swift index 6172ddb83..17e19b9dd 100644 --- a/Packages/Keystore/Sources/Store/WalletKeyStore.swift +++ b/Packages/Keystore/Sources/Store/WalletKeyStore.swift @@ -6,6 +6,7 @@ import Primitives internal import struct Formatters.MnemonicFormatter internal import WalletCorePrimitives +internal import func Gemstone.decodePrivateKey struct WalletKeyStore: Sendable { private let keyStore: WalletCore.KeyStore @@ -41,60 +42,11 @@ struct WalletKeyStore: Sendable { } static func decodeKey(_ key: String, chain: Chain) throws -> PrivateKey { - var data: Data? - for encoding in chain.keyEncodingTypes { - if data != nil { - break - } - switch encoding { - case .base58: - if let decoded = Base58.decodeNoCheck(string: key) { - if decoded.count % 32 == 0 { - data = Data(decoded.prefix(32)) - } else if decoded.count == 37 || decoded.count == 38 { - // WIF format: [1 version] + [32 key] + [4 checksum] (37 bytes, uncompressed) - // or [1 version] + [32 key] + [1 compression flag] + [4 checksum] (38 bytes, compressed) - data = Data(decoded[1..<33]) - } - } - case .hex: - data = Data(hexString: key) - case .base32: - if let decoded = try? decodeBase32Key(string: key, chain: chain) { - data = decoded - } - } - } - - guard - let data = data, - PrivateKey.isValid(data: data, curve: chain.coinType.curve) == true, - let key = PrivateKey(data: data) - else { - throw AnyError("Invalid private key format") - } - return key - } - - static func decodeBase32Key(string: String, chain: Chain) throws -> Data { - switch chain { - case .stellar: - // test against https://lab.stellar.org/account/create - guard - string.count == 56, - string.hasPrefix("S"), - let decoded = Base32.decode(string: string), - decoded.count == 35, - decoded[0] == 0x90 // Mainnet - else { - throw KeystoreError.invalidPrivateKeyEncoding - } - // 35-byte format: [1 version] + [32 payload] + [2 checksum/padding] - return Data(decoded[1 ..< 33]) - - default: - throw KeystoreError.invalidPrivateKeyEncoding + let bytes = try decodePrivateKey(chain: chain.rawValue, value: key) + guard let privateKey = PrivateKey(data: bytes) else { + throw AnyError("Invalid private key") } + return privateKey } func importPrivateKey(id: WalletIdentifier, name: String, key: String, chain: Chain, password: String, source: WalletSource) throws -> Primitives.Wallet { diff --git a/Packages/Keystore/TestKit/KeystoreMock.swift b/Packages/Keystore/TestKit/KeystoreMock.swift index 90a733d26..5a5c4798d 100644 --- a/Packages/Keystore/TestKit/KeystoreMock.swift +++ b/Packages/Keystore/TestKit/KeystoreMock.swift @@ -12,7 +12,7 @@ public struct KeystoreMock: Keystore { public func setupChains(chains: [Primitives.Chain], for wallets: [Primitives.Wallet]) throws -> [Wallet] { [.mock()] } public func deleteKey(for wallet: Primitives.Wallet) throws {} public func getPrivateKey(wallet: Primitives.Wallet, chain: Primitives.Chain) throws -> Data { Data() } - public func getPrivateKey(wallet: Primitives.Wallet, chain: Primitives.Chain, encoding: Primitives.EncodingType) throws -> String { .empty } + public func getPrivateKeyEncoded(wallet: Primitives.Wallet, chain: Primitives.Chain) throws -> String { .empty } public func getMnemonic(wallet: Primitives.Wallet) throws -> [String] { LocalKeystore.words } public func getPasswordAuthentication() throws -> KeystoreAuthentication { .none } public func sign(hash: Data, wallet: Primitives.Wallet, chain: Primitives.Chain) throws -> Data { Data() } diff --git a/Packages/Keystore/Tests/Chain+KeystoreTests.swift b/Packages/Keystore/Tests/Chain+KeystoreTests.swift deleted file mode 100644 index 5980ad6fa..000000000 --- a/Packages/Keystore/Tests/Chain+KeystoreTests.swift +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright (c). Gem Wallet. All rights reserved. - -import Foundation -import Testing -import Primitives -import PrimitivesTestKit - -final class Chain_KeystoreTests { - @Test - func testHasEncodingTypes() { - for chain in Chain.allCases { - #expect(!chain.keyEncodingTypes.isEmpty) - } - } -} diff --git a/Packages/Keystore/Tests/LocalKeystoreTests.swift b/Packages/Keystore/Tests/LocalKeystoreTests.swift index abadec5b2..3ca4cdd91 100644 --- a/Packages/Keystore/Tests/LocalKeystoreTests.swift +++ b/Packages/Keystore/Tests/LocalKeystoreTests.swift @@ -83,22 +83,19 @@ struct LocalKeystoreTests { source: .import ) - let exportedHex = try await keystore.getPrivateKey(wallet: wallet, chain: .solana, encoding: .hex) - let exportedBase58 = try await keystore.getPrivateKey(wallet: wallet, chain: .solana, encoding: .base58) - - #expect(exportedHex == hex) - #expect(exportedBase58 == "DTJi5pMtSKZHdkLX4wxwvjGjf2xwXx1LSuuUZhugYWDV") + let exported = try await keystore.getPrivateKeyEncoded(wallet: wallet, chain: .solana) + #expect(exported == "DTJi5pMtSKZHdkLX4wxwvjGjf2xwXx1LSuuUZhugYWDV") let keystore2 = LocalKeystore.mock() let wallet2 = try await keystore2.importWallet( name: "Test Solana 2", - type: .privateKey(text: exportedBase58, chain: .solana), + type: .privateKey(text: exported, chain: .solana), isWalletsEmpty: true, source: .import ) let exportedKey = try await keystore2.getPrivateKey(wallet: wallet2, chain: .solana) - #expect(Base58.encodeNoCheck(data: exportedKey) == exportedBase58) + #expect(Base58.encodeNoCheck(data: exportedKey) == exported) } } @@ -120,17 +117,6 @@ struct LocalKeystoreTests { #expect(encoded == "5ZRaXVuDePowJjZmKaMjfcuqBVZet6e8QiCjTkGXBn7xhCvoEswUKXiGs2wmPxcqTfJUH28eCC91J1vLSjANNM9v") } - @Test - func importWIF() { - #expect(throws: Never.self) { - let wif = "L1NGZutRxaVotZSfRzGnFYUj42LjEL66ZdAeSDA8CbyASZWizHLA" - let decoded = Base58.decode(string: wif)! - #expect(decoded.count == 34) - - let key = decoded[1 ... 32] - #expect(PrivateKey.isValid(data: key, curve: .secp256k1)) - } - } @Test func deriveAddress() async { diff --git a/Packages/Keystore/Tests/WalletKeyStoreTests.swift b/Packages/Keystore/Tests/WalletKeyStoreTests.swift index c67ca2d1b..68f3c6131 100644 --- a/Packages/Keystore/Tests/WalletKeyStoreTests.swift +++ b/Packages/Keystore/Tests/WalletKeyStoreTests.swift @@ -81,16 +81,6 @@ final class WalletKeyStoreTests { #expect(address == "GADB4BDKTOE36L6QN2JLIPNNJ7EZPSY5BIVKWXLWYZLIPXNQWIRQQZKT") } - @Test func importBitcoinWIF() throws { - let hex = "0x0000000000000000000000000000000000000000000000000000000000000001" - let wif = "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn" - - let keyFromHex = try WalletKeyStore.decodeKey(hex, chain: .bitcoin) - let keyFromWIF = try WalletKeyStore.decodeKey(wif, chain: .bitcoin) - - #expect(keyFromWIF.data == keyFromHex.data) - #expect(CoinType.bitcoin.deriveAddress(privateKey: keyFromWIF) == "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4") - } @Test func addImportWallet() async throws { let store = WalletKeyStore.mock() diff --git a/Packages/Primitives/Sources/EncodingType.swift b/Packages/Primitives/Sources/EncodingType.swift deleted file mode 100644 index adb96cbd8..000000000 --- a/Packages/Primitives/Sources/EncodingType.swift +++ /dev/null @@ -1,11 +0,0 @@ -/* - Generated by typeshare 1.13.3 - */ - -import Foundation - -public enum EncodingType: String, Codable, CaseIterable, Equatable, Sendable { - case hex = "Hex" - case base58 = "Base58" - case base32 = "Base32" -} diff --git a/core b/core index 4734eee8a..e6cf373f2 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 4734eee8a4cffc38397242c0ec91a34f72a49b44 +Subproject commit e6cf373f23d3a9875bbaafa860a7b234e51b82d3