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

Feat/cleanup #29

Open
wants to merge 16 commits into
base: main
Choose a base branch
from
10 changes: 5 additions & 5 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/torusresearch/fetch-node-details-swift.git",
"state" : {
"revision" : "c8d0121fed49ce761f5946bc30e1aafbe1ac5acb",
"revision" : "22bfadf7491d77a0bc1953af002cadbd61383e7d",
"version" : "6.0.2"
}
},
Expand Down Expand Up @@ -122,17 +122,17 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/tkey/tkey-mpc-swift",
"state" : {
"revision" : "8fe0cc8d5cc2ad5d38bf068bc29f6af7e3146d08",
"version" : "3.0.0"
"revision" : "2df2d0a6c51afc76909028eb8542fe78e565d106",
"version" : "3.0.1"
}
},
{
"identity" : "torus-utils-swift",
"kind" : "remoteSourceControl",
"location" : "https://github.com/torusresearch/torus-utils-swift.git",
"state" : {
"revision" : "ff85c3e96bfa29013309b487875c4d9383e4ac80",
"version" : "8.1.1"
"revision" : "608c28404c506983bfec7bbd957632fc0544db8c",
"version" : "8.1.2"
}
},
{
Expand Down
8 changes: 5 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import PackageDescription

let package = Package(
name: "mpc-core-kit-swift",
platforms: [.iOS(.v14), .macOS(.v11)],
platforms: [ .iOS(.v14) ],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
Expand All @@ -15,9 +15,10 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/vapor/jwt-kit.git", from: "4.0.0"),
.package(url: "https://github.com/torusresearch/tss-client-swift.git", from: "4.0.0"),
.package(url: "https://github.com/tkey/tkey-mpc-swift", from: "3.0.0"),
.package(url: "https://github.com/tkey/tkey-mpc-swift", from: "3.0.1"),
.package(url: "https://github.com/torusresearch/customauth-swift-sdk", from: "10.0.1"),
.package(url: "https://github.com/Web3Auth/single-factor-auth-swift", from: "5.0.0")
.package(url: "https://github.com/Web3Auth/single-factor-auth-swift", from: "5.0.0"),
.package(url: "https://github.com/auth0/JWTDecode.swift", from: "3.1.0")
],

targets: [
Expand All @@ -30,6 +31,7 @@ let package = Package(
.product(name: "SingleFactorAuth", package: "single-factor-auth-swift"),
.product(name: "tkey", package: "tkey-mpc-swift" ),
.product(name: "tssClientSwift", package: "tss-client-swift" ),
.product(name: "JWTDecode", package: "JWTDecode.swift")
]
),
.testTarget(
Expand Down
90 changes: 90 additions & 0 deletions Sources/mpc-core-kit-swift/CoreKitError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import Foundation

public enum CoreKitError: Error {
case invalidResult
case invalidInput
case notFound(msg: String)
case factorKeyUnavailable
case metadataPubKeyUnavailable
case shareIndexNotFound
case notLoggedIn
case notInitialized
case keyDetailsNotFound
case invalidVerifierOrVerifierID
case invalidNode
case invalidMetadataEndpoint
case invalidPostboxKey
case invalidSessionData
case invalidTKey
case nodeDetailsMissing
case invalidMetadataUrl
case invalidOAuthKey
case invalidHashKey
case invalidAuthSignatures
case invalidFactorKey
case factorKeyAndFactorPubMismatch
case invalidMetadataPubKey
case currentFactorNotHashFactor
case requireUncompressedPublicKey
case invalidStore
case noTssTags

public var errorDescription: String {
switch self {
case .invalidResult:
return "Invalid Result"
case let .notFound(msg: msg):
return msg
case .metadataPubKeyUnavailable:
return "Metadata public key is not available"
case .invalidInput:
return "Invalid input"
case .factorKeyUnavailable:
return "Factor key unavailable"
case .shareIndexNotFound:
return "Share index not found"
case .notLoggedIn:
return "User is not logged in"
case .notInitialized:
return "User is not initialized"
case .keyDetailsNotFound:
return "Key details not found"
case .invalidVerifierOrVerifierID:
return "Invalid verifier or verifierID"
case .invalidNode:
return "Invalid verifier or verifierID"
case .invalidMetadataEndpoint:
return "Invalid verifier or verifierID"
case .invalidPostboxKey:
return "Invalid postbox key"
case .invalidSessionData:
return "Invalid session data"
case .invalidTKey:
return "Invalid tKey"
case .nodeDetailsMissing:
return "Node details absent"
case .invalidMetadataUrl:
return "Invalid metadata url"
case .invalidOAuthKey:
return "Invalid OAuthKey"
case .invalidHashKey:
return "Invalid hash key"
case .invalidAuthSignatures:
return "Invalid auth signatures"
case .invalidFactorKey:
return "Invalid factor key"
case .factorKeyAndFactorPubMismatch:
return "Factor key does not match factor public key"
case .invalidMetadataPubKey:
return "Invalid metadata public key"
case .currentFactorNotHashFactor:
return "Current factor is not hash factor"
case .requireUncompressedPublicKey:
return "Public key needs to be in uncompressed format"
case .invalidStore:
return "Invalid Store"
case .noTssTags:
return "No Tss tags have been set"
}
}
}
138 changes: 30 additions & 108 deletions Sources/mpc-core-kit-swift/CoreKitStorage.swift
Original file line number Diff line number Diff line change
@@ -1,139 +1,61 @@
//
// File.swift
//
//
// Created by CW Lee on 07/02/2024.
//

import Foundation

public class CoreKitStorage {
internal static var instance : CoreKitStorage? ;

public var storage : ILocalStorage
private var storeKey : String

public init(storeKey : String, storage: ILocalStorage) {
public var storage: ILocalStorage
private var storeKey: String

public init(storeKey: String, storage: ILocalStorage) {
self.storage = storage
self.storeKey = storeKey
}

// static func getInstance( storeKey: String , storage: ILocalStorage? = nil) throws -> CoreKitStorage {
// guard let localInstance = self.instance else {
// guard let lStorage = storage else {
// throw "no storage provided or found"
// }
// let local = CoreKitStorage.init(storeKey: storeKey, storage: lStorage)
// CoreKitStorage.instance = local
// return local
// }
// return localInstance
// }


public func resetStore() async throws -> Data {
let result = try await self.storage.get(key: self.storeKey)
let result = try await storage.get(key: storeKey)
let payload = try JSONSerialization.data(withJSONObject: [:])
try await self.storage.set(key: self.storeKey, payload: payload)

try await storage.set(key: storeKey, payload: payload)

return result
}

public func toJsonStr() async throws -> String {
let result = try await self.storage.get(key: self.storeKey)

public func getStringified() async throws -> String {
// TODO: JSONDecoder and appropriate types, if applicable
let result = try await storage.get(key: storeKey)
guard let resultStr = String(data: result, encoding: .utf8) else {
throw "invalid store"
throw CoreKitError.invalidStore
}
return resultStr
}

public func getStore() async throws -> [String: Any] {
let result = try await self.storage.get(key: self.storeKey)
let result = try await storage.get(key: storeKey)
if result.isEmpty { return [:] }
let store = try JSONSerialization.jsonObject(with: result) as? [String: Any]
guard let storeUnwrapped = store else {
return [:]
throw CoreKitError.invalidStore
}
return storeUnwrapped
}

public func get<T>(key:String) async throws -> T {
let store = try await self.getStore()


public func get<T>(key: String) async throws -> T {
let store = try await getStore()
guard let item = store[key] as? T else {
throw "key \(key) value not found"
throw CoreKitError.notFound(msg: "key \(key) value not found")
}
return item
}

public func set<T>(key:String, payload: T) async throws {
var store : [String:Any] = try await self.getStore()
store.updateValue( payload, forKey: key)


public func set<T>(key: String, payload: T) async throws {
var store: [String: Any] = try await getStore()
store.updateValue(payload, forKey: key)
let jsonData = try JSONSerialization.data(withJSONObject: store)
try await self.storage.set(key: self.storeKey, payload: jsonData)
try await storage.set(key: storeKey, payload: jsonData)
}
public func remove(key:String) async throws {
var store = try await self.getStore()

public func remove(key: String) async throws {
var store = try await getStore()
store[key] = nil
let jsonData = try JSONSerialization.data(withJSONObject: store)
try await self.storage.set(key: self.storeKey, payload: jsonData)
}

}

// Example implementation of Factor Storage Protocol (Interface)
class DeviceFactorStorage : IFactorStorage {
let storage: CoreKitStorage

public init(storage: CoreKitStorage) {
self.storage = storage
}

public func setFactor(metadataPubKey: String, factorKey: String) async throws {
var localMetadata : [String: Any] = [:]
let result : [String: Any]? = try? await self.storage.get(key: metadataPubKey)
if let result = result {
localMetadata = result
}
localMetadata["factorKey"] = factorKey
try await self.storage.set(key: metadataPubKey, payload: localMetadata)
}

public func getFactor(metadataPubKey: String) async throws -> String {
let localMetadata : [String: Any]? = try? await self.storage.get(key: metadataPubKey)
guard let localMetadata = localMetadata, let deviceFactor = localMetadata["factorKey"] as? String else {
throw "device factor not found"
}
return deviceFactor
}
}


extension MpcCoreKit {
public func getDeviceFactor () async throws -> String {
// getMetadataPublicKey compressed
guard let metadataPubKey = self.appState.metadataPubKey else {
throw "metadataPubKey is not available"
}

let deviceFactorStorage = DeviceFactorStorage(storage: self.coreKitStorage)
return try await deviceFactorStorage.getFactor(metadataPubKey: metadataPubKey)
}

public func setDeviceFactor ( factorKey: String ) async throws {
guard let metadataPubKey = self.appState.metadataPubKey else {
throw "metadataPubKey is not available"
}
let deviceFactorStorage = DeviceFactorStorage(storage: self.coreKitStorage)
try await deviceFactorStorage.setFactor(metadataPubKey: metadataPubKey, factorKey: factorKey)
}

internal func resetDeviceFactorStore () async throws {
guard let metadataPubKey = self.appState.metadataPubKey else {
throw "metadataPubKey is not available"
}
try await self.coreKitStorage.set(key: metadataPubKey, payload: [:])
try await storage.set(key: storeKey, payload: jsonData)
}
}
25 changes: 25 additions & 0 deletions Sources/mpc-core-kit-swift/DeviceFactorStorage.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import Foundation

public class DeviceFactorStorage: IFactorStorage {
let storage: CoreKitStorage

public init(storage: CoreKitStorage) {
self.storage = storage
}

public func setFactor(metadataPubKey: String, factorKey: String) async throws {
var localMetadata: [String: Any] = try await storage.get(key: metadataPubKey)

localMetadata["factorKey"] = factorKey
try await storage.set(key: metadataPubKey, payload: localMetadata)
}

public func getFactor(metadataPubKey: String) async throws -> String {
let localMetadata: [String: Any] = try await storage.get(key: metadataPubKey)
guard let deviceFactor = localMetadata["factorKey"] as? String else {
throw CoreKitError.notFound(msg: "device factor not found")
}
return deviceFactor
}
}

Loading
Loading