last hackathon effort
This commit is contained in:
parent
1e336b256b
commit
0f7ed09c81
|
@ -227,8 +227,8 @@
|
|||
0D64CEB124A3CDA90080AA4F /* CameraAccessHelper.swift */,
|
||||
0D64CEAE24A3CDA80080AA4F /* MnemonicSeedPhraseHandling.swift */,
|
||||
0D64CEAC24A3CDA80080AA4F /* MnemonicSeedPhraseProvider.swift */,
|
||||
0D64CEAD24A3CDA80080AA4F /* QRCodeGenerator.swift */,
|
||||
0D64CEAA24A3CDA80080AA4F /* SeedManagement.swift */,
|
||||
0D64CEAD24A3CDA80080AA4F /* QRCodeGenerator.swift */,
|
||||
0D64CEB324A3CDA90080AA4F /* SimpleLogger.swift */,
|
||||
0D64CEAB24A3CDA80080AA4F /* String+Zcash.swift */,
|
||||
0D64CEAF24A3CDA80080AA4F /* URL+Zcash.swift */,
|
||||
|
|
|
@ -10,6 +10,7 @@ import Foundation
|
|||
|
||||
class ZircleDataStorage {
|
||||
static let usernameKey = "zircleusername"
|
||||
static let autoIdKey = "autoid"
|
||||
static var `default`: ZircleDataStorage = ZircleDataStorage()
|
||||
|
||||
private init() {}
|
||||
|
@ -21,4 +22,13 @@ class ZircleDataStorage {
|
|||
UserDefaults.standard.string(forKey: Self.usernameKey) ?? ""
|
||||
}
|
||||
|
||||
var autoId: String {
|
||||
if let autoid = UserDefaults.standard.string(forKey: Self.autoIdKey) {
|
||||
return autoid
|
||||
}
|
||||
|
||||
let newId = "zirclesUser\(Int.random(in: 0 ... Int.max))"
|
||||
UserDefaults.standard.setValue(newId, forKey: Self.autoIdKey)
|
||||
return newId
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,7 +108,7 @@ struct CreateNewZircleDescription: View {
|
|||
)
|
||||
}.padding(.all, 0)
|
||||
Button(action: {
|
||||
|
||||
// ZircleServic
|
||||
}, label: {
|
||||
Text("Create New Zircle")
|
||||
.font(.system(size: 20, weight: .bold, design: .default))
|
||||
|
|
|
@ -8,19 +8,21 @@
|
|||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
import ZcashLightClientKit
|
||||
enum ZircleServiceError: Error {
|
||||
case generalError(message: String)
|
||||
}
|
||||
|
||||
|
||||
protocol ZircleService {
|
||||
func createNewZircle(name: String, goal zatoshi: Int64, frequency: ZircleFrequency, endDate: ZircleEndDate, spendingKey: String) throws -> Future<ZircleEntity, Error>
|
||||
func closeZircle(name: String) throws
|
||||
func contribute(zatoshi: Int64, zircle: ZircleEntity) throws
|
||||
func allOpenZircles() throws -> [ZircleEntity]?
|
||||
func contribute(zatoshi: Int64, zircle: ZircleEntity) -> Future<PendingTransactionEntity, Error>
|
||||
func allOpenZircles() -> Future<[ZircleEntity], Error>
|
||||
func allContributions(from zircle: ZircleEntity) -> Future<[ZircleOverallContribution],Error>
|
||||
func openInvite(_ url: URL) -> Future<Int,Error>
|
||||
|
||||
}
|
||||
|
||||
protocol ZircleOverallContribution {
|
||||
var from: String { get set }
|
||||
var zAddr: String { get set }
|
||||
|
@ -45,8 +47,8 @@ enum ZircleFrequency: Int {
|
|||
case daily = 0
|
||||
case weekly
|
||||
case monthly
|
||||
|
||||
}
|
||||
|
||||
enum ZircleEndDate {
|
||||
case onDate(date: Date)
|
||||
case atWill
|
||||
|
@ -73,17 +75,103 @@ import MnemonicSwift
|
|||
|
||||
extension CombineSynchronizer: ZircleService {
|
||||
|
||||
|
||||
func allOpenZircles() -> Future<[ZircleEntity], Error> {
|
||||
Future<[ZircleEntity], Error>() { promise in
|
||||
DispatchQueue.global().async { [weak self] in
|
||||
guard let self = self else {
|
||||
return
|
||||
}
|
||||
|
||||
let accountRepository = AccountRepositoryBuilder.repository(initializer: self.initializer)
|
||||
|
||||
guard let accounts = try? accountRepository.getAccounts() else {
|
||||
promise(.failure(ZircleServiceError.generalError(message: "could not get accounts")))
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
var zircles = [ZircleEntity]()
|
||||
for account in accounts {
|
||||
|
||||
let foundZircles = try self.synchronizer.allClearedTransactions(accountIndex: account.account)
|
||||
|
||||
.compactMap({ (confirmedTx) -> ZircleEntity? in
|
||||
|
||||
guard let memo = confirmedTx.memo?.asZcashTransactionMemo() else {
|
||||
return nil
|
||||
}
|
||||
let zircle = try CreateZircleMessage(jsonString: memo)
|
||||
|
||||
return ConcreteZircle(name: zircle.name, goal: Int64(zircle.goal), frequency: zircle.frequency.rawValue, endDate: TimeInterval(zircle.end), accountIndex: account.account, address: account.address)
|
||||
})
|
||||
|
||||
zircles.append(contentsOf: foundZircles)
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
promise(.success(zircles))
|
||||
} catch {
|
||||
promise(.failure(ZircleServiceError.generalError(message: "error: \(error)")))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func closeZircle(name: String) throws {
|
||||
|
||||
}
|
||||
|
||||
func contribute(zatoshi: Int64, zircle: ZircleEntity) throws {
|
||||
func contribute(zatoshi: Int64, zircle: ZircleEntity) -> Future<PendingTransactionEntity, Error> {
|
||||
Future<PendingTransactionEntity, Error>() { promise in
|
||||
|
||||
|
||||
guard let mainSpendingKey = SeedManager.default.getKeys()?.first else {
|
||||
return
|
||||
}
|
||||
|
||||
guard let replyToAddr = self.initializer.getAddress() else {
|
||||
promise(.failure(ZircleServiceError.generalError(message: "could not create contribution")))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
let contribution = ContributionJoin.with { (contrib) in
|
||||
contrib.autoid = ZircleDataStorage.default.autoId
|
||||
contrib.replyTo = replyToAddr
|
||||
contrib.from = ZircleDataStorage.default.username
|
||||
|
||||
}
|
||||
|
||||
guard let contributionMemo = try? contribution.jsonString() else {
|
||||
promise(.failure(ZircleServiceError.generalError(message: "could not create contribution")))
|
||||
return
|
||||
}
|
||||
|
||||
guard contributionMemo.count <= 512 else {
|
||||
promise(.failure(ZircleServiceError.generalError(message: "could not create contribution. contribution message exceeds memo size")))
|
||||
return
|
||||
}
|
||||
self.send(with: mainSpendingKey,
|
||||
zatoshi: zatoshi,
|
||||
to: zircle.address,
|
||||
memo: contributionMemo,
|
||||
from: zircle.accountIndex)
|
||||
.sink { (errorCompletion) in
|
||||
switch errorCompletion {
|
||||
case .failure(let error):
|
||||
promise(.failure(error))
|
||||
default:
|
||||
break
|
||||
}
|
||||
} receiveValue: { (pendingTransaction) in
|
||||
promise(.success(pendingTransaction))
|
||||
}.store(in: &self.cancellables)
|
||||
}
|
||||
}
|
||||
|
||||
func allOpenZircles() throws -> [ZircleEntity]? {
|
||||
nil
|
||||
}
|
||||
|
||||
func allContributions(from zircle: ZircleEntity) -> Future<[ZircleOverallContribution], Error> {
|
||||
Future<[ZircleOverallContribution], Error>() { promise in
|
||||
|
@ -157,11 +245,11 @@ extension CombineSynchronizer: ZircleService {
|
|||
|
||||
// create zircle struct
|
||||
let zircle = ConcreteZircle(name: name,
|
||||
goal: zatoshi,
|
||||
frequency: frequency.rawValue,
|
||||
endDate: end,
|
||||
accountIndex: Int(accountIndex),
|
||||
address: zAddr)
|
||||
goal: zatoshi,
|
||||
frequency: frequency.rawValue,
|
||||
endDate: end,
|
||||
accountIndex: Int(accountIndex),
|
||||
address: zAddr)
|
||||
|
||||
|
||||
// get supporting wallet spending keys to create zircle
|
||||
|
@ -189,10 +277,10 @@ extension CombineSynchronizer: ZircleService {
|
|||
return
|
||||
}
|
||||
// save before sending
|
||||
try SeedManager.default.saveKeys(name,
|
||||
phrase: seedPhrase,
|
||||
height: height,
|
||||
spendingKey: extendedSpendingKey)
|
||||
try SeedManager.default.saveKeys(name,
|
||||
phrase: seedPhrase,
|
||||
height: height,
|
||||
spendingKey: extendedSpendingKey)
|
||||
// fund zircle
|
||||
self.send(with: spendingKey,
|
||||
zatoshi: 1000,
|
||||
|
@ -200,15 +288,15 @@ extension CombineSynchronizer: ZircleService {
|
|||
memo: memo,
|
||||
from: 0)
|
||||
.sink { errorSubscriber in
|
||||
switch errorSubscriber {
|
||||
case .failure(let underlyingError):
|
||||
promise(.failure(underlyingError))
|
||||
default:
|
||||
break
|
||||
}
|
||||
} receiveValue: { (p) in
|
||||
promise(.success(zircle))
|
||||
}.store(in: &storage)
|
||||
switch errorSubscriber {
|
||||
case .failure(let underlyingError):
|
||||
promise(.failure(underlyingError))
|
||||
default:
|
||||
break
|
||||
}
|
||||
} receiveValue: { (p) in
|
||||
promise(.success(zircle))
|
||||
}.store(in: &storage)
|
||||
|
||||
} catch {
|
||||
promise(.failure(error))
|
||||
|
@ -225,6 +313,17 @@ extension CombineSynchronizer: ZircleService {
|
|||
}
|
||||
|
||||
func openInvite(_ url: URL) throws {
|
||||
guard let invite = LiberatedInviteHandler.parseInvite(url) else {
|
||||
throw ZircleServiceError.generalError(message: "URL: \(url) - is not a valid liberated invite url")
|
||||
}
|
||||
|
||||
|
||||
// this should now rewind and try to sync again.
|
||||
self.stop()
|
||||
|
||||
try initializer.rewindTo(invite.height)
|
||||
|
||||
self.start(retry: true)
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue