mirror of
https://github.com/lil-org/tokenary.git
synced 2024-12-15 06:56:34 +03:00
69 lines
2.5 KiB
Swift
69 lines
2.5 KiB
Swift
// Copyright © 2021 Encrypted Ink. All rights reserved.
|
|
|
|
import Foundation
|
|
import Web3Swift
|
|
|
|
struct AccountsService {
|
|
|
|
private static let keychainKey = "EncryptedInkStorage"
|
|
|
|
static func validateAccountKey(_ key: String) -> Bool {
|
|
let address = try? EthPrivateKey(hex: key).address().value()
|
|
return address != nil
|
|
}
|
|
|
|
static func addAccount(privateKey: String) -> Account? {
|
|
guard
|
|
let addressBytes = try? EthPrivateKey(hex: privateKey).address().value()
|
|
else {
|
|
return nil
|
|
}
|
|
// TODO: checksum address
|
|
let address = addressBytes.toPrefixedHexString()
|
|
let account = Account(privateKey: privateKey, address: address)
|
|
var accounts = getAccounts()
|
|
guard !accounts.contains(where: { $0.address == address }) else { return nil }
|
|
accounts.append(account)
|
|
saveInKeychain(accounts: accounts)
|
|
return account
|
|
}
|
|
|
|
static func removeAccount(_ account: Account) {
|
|
var accounts = getAccounts()
|
|
accounts.removeAll(where: {$0.address == account.address })
|
|
|
|
saveInKeychain(accounts: accounts)
|
|
}
|
|
|
|
static func getAccounts() -> [Account] {
|
|
return loadAccountsFromKeychain() ?? []
|
|
}
|
|
|
|
private static func saveInKeychain(accounts: [Account]) {
|
|
guard let data = try? JSONEncoder().encode(accounts) else { return }
|
|
let query = [kSecClass as String: kSecClassGenericPassword as String,
|
|
kSecAttrAccount as String: keychainKey,
|
|
kSecValueData as String: data] as [String: Any]
|
|
|
|
SecItemDelete(query as CFDictionary)
|
|
SecItemAdd(query as CFDictionary, nil)
|
|
}
|
|
|
|
private static func loadAccountsFromKeychain() -> [Account]? {
|
|
guard let returnDataQueryValue = kCFBooleanTrue else { return nil }
|
|
let query = [kSecClass as String: kSecClassGenericPassword,
|
|
kSecAttrAccount as String: keychainKey,
|
|
kSecReturnData as String: returnDataQueryValue,
|
|
kSecMatchLimit as String: kSecMatchLimitOne] as [String: Any]
|
|
|
|
var dataTypeRef: AnyObject?
|
|
let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef)
|
|
if status == noErr, let data = dataTypeRef as? Data {
|
|
let accounts = try? JSONDecoder().decode([Account].self, from: data)
|
|
return accounts
|
|
} else {
|
|
return nil
|
|
}
|
|
}
|
|
}
|