132 lines
6.0 KiB
Swift
132 lines
6.0 KiB
Swift
//
|
|
// AccountServiceChangeKey.swift
|
|
// PayCash
|
|
//
|
|
// Created by Alexandr Serpokrylow on 16.02.2022.
|
|
// Copyright © 2022 AM. All rights reserved.
|
|
//
|
|
|
|
import Foundation
|
|
import EosioSwift
|
|
|
|
extension Account.Service {
|
|
class ChangeKey: Common.Service.Provider {
|
|
|
|
private(set) var accounts = [Account.Model.ChangeKey]()
|
|
private var requests = 0
|
|
|
|
func fetch(privateKey: String, keyType: Account.KeyType, _ completion: @escaping Completion.Network) {
|
|
guard let publicKey = privateKey.publicKey(), let newPrivateKey = try? EOSPrivateKey() else {
|
|
completion(.error(L10n.Error.Accounts.keyInvalid))
|
|
return
|
|
}
|
|
|
|
Network.accounts.fetch(publicKey: publicKey) { (collection) in
|
|
if (collection.isEmpty) {
|
|
completion(.error(L10n.Error.Accounts.empty))
|
|
} else {
|
|
self.requests = collection.count
|
|
collection.forEach { username in
|
|
Network.accounts.account(username, completion: { response in
|
|
DispatchQueue.global().async {
|
|
|
|
guard let accountInfo = response else {
|
|
completion(.error(L10n.Error.Accounts.empty))
|
|
return
|
|
}
|
|
|
|
let newAccounts = self.prepareAccountInfo(username: username,
|
|
publicKey: publicKey,
|
|
keyType: keyType,
|
|
newPrivateKey: newPrivateKey,
|
|
accountPermissions: accountInfo.permissions)
|
|
self.accounts += newAccounts
|
|
self.requests -= 1
|
|
|
|
if (self.requests == 0) {
|
|
DispatchQueue.main.async { completion(nil) }
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func prepareAccountInfo(username: String,
|
|
publicKey: String,
|
|
keyType: Account.KeyType,
|
|
newPrivateKey: EOSPrivateKey,
|
|
accountPermissions: [Permission]
|
|
) -> [Account.Model.ChangeKey] {
|
|
var accounts: [Account.Model.ChangeKey] = []
|
|
let permissions = accountPermissions.filter {
|
|
switch keyType {
|
|
case .active:
|
|
return $0.permName == Account.KeyType.active.rawValue && $0.requiredAuth.keys.first?.key == publicKey
|
|
case .owner:
|
|
return $0.requiredAuth.keys.first?.key == publicKey
|
|
}
|
|
}
|
|
.sorted { $0.permName > $1.permName }
|
|
|
|
permissions.forEach { permission in
|
|
accounts.append(Account.Model.ChangeKey(username: username, permission: permission, privateKey: newPrivateKey.base58, publicKey: newPrivateKey.publicKey.base58))
|
|
}
|
|
return accounts
|
|
}
|
|
|
|
|
|
func validatePrivateKey(privateKey: String) -> Bool {
|
|
let privateKey = try? EOSPrivateKey(base58: privateKey)
|
|
return privateKey != nil
|
|
}
|
|
|
|
func validatePublicKey(publicKey: String) -> Bool {
|
|
let publicKey = try? EOSPublicKey(base58: publicKey)
|
|
return publicKey != nil
|
|
}
|
|
|
|
func validateKeyPair(privateKey: String, publicKey: String) -> Bool {
|
|
guard let privateKey = try? EOSPrivateKey(base58: privateKey) else {
|
|
return false
|
|
}
|
|
return privateKey.publicKey.base58 == publicKey
|
|
}
|
|
|
|
func submit(privateKey: String, accounts: [Account.Model.ChangeKey], password: String, _ completion: @escaping (String?, NSError?) -> Void) {
|
|
|
|
var actions = [(contract: Network.Model.Contract, action: Network.Model.Blockchain.Action, data: Codable)]()
|
|
for account in accounts {
|
|
if let data = createChangeKeyData(account: account) {
|
|
actions.append((contract: .eosio, action: .updateauth, data: data))
|
|
}
|
|
}
|
|
|
|
Network.Service.Blockchain.execute(actions: actions, privateKeys: [privateKey]) { (result) in
|
|
if case .success(let trxId) = result {
|
|
Accounts().updateCredentialsIfNeeded(accounts: accounts, password: password)
|
|
completion(trxId, nil)
|
|
} else {
|
|
completion(nil, .error(result))
|
|
}
|
|
}
|
|
}
|
|
|
|
private func createChangeKeyData(account: Account.Model.ChangeKey) -> Network.Model.Blockchain.UpdateAuth? {
|
|
var keys: [Network.Model.Blockchain.KeyWeight] = []
|
|
|
|
guard let eosioPublicKey = (try? Data(eosioPublicKey: account.publicKey).toEosioK1PublicKey) else { return nil }
|
|
|
|
let key = Network.Model.Blockchain.KeyWeight(key: eosioPublicKey, weight: 1)
|
|
keys.append(key)
|
|
|
|
let auth = Network.Model.Blockchain.Authority(threshold: 1, keys: keys, waits: [], accounts: [])
|
|
let parent = account.permission.permName == Account.KeyType.active.rawValue ? Account.KeyType.owner.rawValue : ""
|
|
let permission = account.permission.permName
|
|
|
|
return Network.Model.Blockchain.UpdateAuth(account: account.username, permission: permission, parent: parent, auth: auth)
|
|
}
|
|
}
|
|
}
|