Skip to content

Commit

Permalink
Merge branch '10-wallet' into develop
Browse files Browse the repository at this point in the history
# Conflicts:
#	SolardVPNCommunityCoreiOS/SOLARdVPNCommunityCoreiOS/Root/DVPNServer.swift
  • Loading branch information
VictoriaKostyleva committed Oct 5, 2022
2 parents 2a51f3c + 11b4cf5 commit 9dd7779
Show file tree
Hide file tree
Showing 10 changed files with 218 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@
923C372E28EB0BEE003CFC03 /* continents.json in Resources */ = {isa = PBXBuildFile; fileRef = 923C372D28EB0BED003CFC03 /* continents.json */; };
923C373128EB0CB2003CFC03 /* CountryExtra.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C373028EB0CB2003CFC03 /* CountryExtra.swift */; };
923C373328EB150A003CFC03 /* GetContinentResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C373228EB150A003CFC03 /* GetContinentResponse.swift */; };
923C373728EC791E003CFC03 /* WalletRouteCollection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C373628EC791E003CFC03 /* WalletRouteCollection.swift */; };
923C373A28EC79E8003CFC03 /* Wallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C373928EC79E8003CFC03 /* Wallet.swift */; };
923C373C28ED79A2003CFC03 /* Mnemonic.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C373B28ED79A2003CFC03 /* Mnemonic.swift */; };
923C373E28EDB109003CFC03 /* PostMnemonicResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 923C373D28EDB109003CFC03 /* PostMnemonicResponse.swift */; };
92D6B3FD28E19E20004CF9DF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D6B3FC28E19E20004CF9DF /* AppDelegate.swift */; };
92D6B3FF28E19E20004CF9DF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D6B3FE28E19E20004CF9DF /* SceneDelegate.swift */; };
92D6B40128E19E20004CF9DF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 92D6B40028E19E20004CF9DF /* ViewController.swift */; };
Expand Down Expand Up @@ -247,6 +251,10 @@
923C372D28EB0BED003CFC03 /* continents.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = continents.json; sourceTree = "<group>"; };
923C373028EB0CB2003CFC03 /* CountryExtra.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CountryExtra.swift; sourceTree = "<group>"; };
923C373228EB150A003CFC03 /* GetContinentResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetContinentResponse.swift; sourceTree = "<group>"; };
923C373628EC791E003CFC03 /* WalletRouteCollection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WalletRouteCollection.swift; sourceTree = "<group>"; };
923C373928EC79E8003CFC03 /* Wallet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Wallet.swift; sourceTree = "<group>"; };
923C373B28ED79A2003CFC03 /* Mnemonic.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mnemonic.swift; sourceTree = "<group>"; };
923C373D28EDB109003CFC03 /* PostMnemonicResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostMnemonicResponse.swift; sourceTree = "<group>"; };
92D6B3F928E19E20004CF9DF /* SOLARdVPNCommunityCoreiOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SOLARdVPNCommunityCoreiOS.app; sourceTree = BUILT_PRODUCTS_DIR; };
92D6B3FC28E19E20004CF9DF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
92D6B3FE28E19E20004CF9DF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -597,6 +605,7 @@
923C372328E72FDA003CFC03 /* RouteCollections */ = {
isa = PBXGroup;
children = (
923C373528EC7904003CFC03 /* Wallet */,
923C372428E72FF0003CFC03 /* Nodes */,
225A83A428EC297500F66619 /* Tunnel */,
);
Expand Down Expand Up @@ -630,6 +639,25 @@
path = Models;
sourceTree = "<group>";
};
923C373528EC7904003CFC03 /* Wallet */ = {
isa = PBXGroup;
children = (
923C373828EC79D9003CFC03 /* Models */,
923C373628EC791E003CFC03 /* WalletRouteCollection.swift */,
);
path = Wallet;
sourceTree = "<group>";
};
923C373828EC79D9003CFC03 /* Models */ = {
isa = PBXGroup;
children = (
923C373B28ED79A2003CFC03 /* Mnemonic.swift */,
923C373928EC79E8003CFC03 /* Wallet.swift */,
923C373D28EDB109003CFC03 /* PostMnemonicResponse.swift */,
);
path = Models;
sourceTree = "<group>";
};
92D6B3F028E19E20004CF9DF = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -1001,6 +1029,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
923C373A28EC79E8003CFC03 /* Wallet.swift in Sources */,
92D6B40128E19E20004CF9DF /* ViewController.swift in Sources */,
22C3EEED28E48D9A007DB01B /* SentinelNode+Ext.swift in Sources */,
923C372628EAE93E003CFC03 /* Encoder.swift in Sources */,
Expand All @@ -1015,6 +1044,7 @@
92D6B46F28E47E2E004CF9DF /* NodesService.swift in Sources */,
22C3EEA728E4733C007DB01B /* Config.swift in Sources */,
22C3EEE528E48D9A007DB01B /* NEVPNManager+Ext.swift in Sources */,
923C373C28ED79A2003CFC03 /* Mnemonic.swift in Sources */,
22488AA028E72C4E00FE29C3 /* UserDefaultsStorageStrategy.swift in Sources */,
22C3EECA28E48B52007DB01B /* TunnelManager.swift in Sources */,
22C3EED028E48B52007DB01B /* TunnelModel.swift in Sources */,
Expand All @@ -1041,6 +1071,7 @@
22C3EED428E48B52007DB01B /* TunnelsService.swift in Sources */,
225A839D28EAE54400F66619 /* SecurityService.swift in Sources */,
22C3EEE628E48D9A007DB01B /* TunnelConfiguration+Ext.swift in Sources */,
923C373728EC791E003CFC03 /* WalletRouteCollection.swift in Sources */,
22C3EEE828E48D9A007DB01B /* Serializer.swift in Sources */,
22C3EEE728E48D9A007DB01B /* NEVPNStatus+Ext.swift in Sources */,
92D6B41428E1E133004CF9DF /* DVPNServer.swift in Sources */,
Expand All @@ -1064,6 +1095,7 @@
22C3EEAA28E4733C007DB01B /* NETunnelProviderProtocol+Extension.swift in Sources */,
22488AA328E72C4E00FE29C3 /* StoresWallet.swift in Sources */,
22C3EED128E48B52007DB01B /* TunnelStatus.swift in Sources */,
923C373E28EDB109003CFC03 /* PostMnemonicResponse.swift in Sources */,
923C373328EB150A003CFC03 /* GetContinentResponse.swift in Sources */,
923C372A28EAFAA5003CFC03 /* NodesServiceError.swift in Sources */,
225A836C28EACE6C00F66619 /* ConnectionNodeModel.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ extension CommonContext: HasTunnelManager {}
protocol HasSessionsService { var sessionsService: SessionsServiceType { get } }
extension CommonContext: HasSessionsService {}

protocol HasSecurityService { var securityService: SecurityService { get } }
extension CommonContext: HasSecurityService {}

// MARK: - Storages

protocol HasConnectionInfoStorage { var connectionInfoStorage: StoresConnectInfo { get } }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ enum ClientConstants {
static let apiPath = "api"

static let backendURL = URL(string: "https://BACKEND")!

static let denom = "udvpn"
}

final class ApplicationConfiguration: ClientConnectionConfigurationType {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ extension DVPNServer {
do {
let api = app.grouped(.init(stringLiteral: ClientConstants.apiPath))
try api.register(collection: NodesRouteCollection(context: context))
try api.register(collection: WalletRouteCollection(context: context))
try api.register(
collection:
TunnelRouteCollection(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@ import Foundation
struct GetContinentResponse: Codable {
let code: String
let nodesCount: Int

init(code: String, nodesCount: Int) {
self.code = code
self.nodesCount = nodesCount
}
}

// MARK: - Codable implementation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import GRPC

private struct Constants {
let timeout: TimeInterval = 15
let denom = "udvpn"
}

private let constants = Constants()
Expand Down Expand Up @@ -129,7 +128,7 @@ extension ConnectionNodeModel {
case .success(let balances):
guard balances
.contains(
where: { $0.denom == constants.denom && Int($0.amount) ?? 0 >= self.context.walletService.fee }
where: { $0.denom == ClientConstants.denom && Int($0.amount) ?? 0 >= self.context.walletService.fee }
) else {
self.delegate?.show(warning: WalletServiceError.notEnoughTokens.body)
self.delegate?.set(isLoading: false)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
//
// Mnemonic.swift
// SOLARdVPNCommunityCoreiOS
//
// Created by Viktoriia Kostyleva on 05.10.2022.
//

import Foundation

struct Mnemonic: Codable {
let mnemonic: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// PostMnemonicResponse.swift
// SOLARdVPNCommunityCoreiOS
//
// Created by Viktoriia Kostyleva on 05.10.2022.
//

import Foundation

struct PostMnemonicResponse: Codable {
let wallet: Wallet
let mnemonic: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Wallet.swift
// SOLARdVPNCommunityCoreiOS
//
// Created by Viktoriia Kostyleva on 04.10.2022.
//

import Foundation

struct Wallet: Codable {
let address: String
let balance: Int
let currency: String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
//
// WalletRouteCollection.swift
// SOLARdVPNCommunityCoreiOS
//
// Created by Viktoriia Kostyleva on 04.10.2022.
//

import Foundation
import Vapor

struct WalletRouteCollection: RouteCollection {
let context: HasSecurityService & HasWalletStorage & HasWalletService

func boot(routes: RoutesBuilder) throws {
routes.get("wallet", use: getWallet)
routes.put("wallet", use: putWallet)
routes.post("wallet", use: postWallet)
routes.delete("wallet", use: deleteWallet)
}
}

extension WalletRouteCollection {
func getWallet(_ req: Request) async throws -> String {
try await withCheckedThrowingContinuation({ (continuation: CheckedContinuation<String, Error>) in
getWallet() { result in
switch result {
case let .failure(error):
continuation.resume(throwing: Abort(.init(statusCode: 500), reason: error.localizedDescription))

case let .success(wallet):
Encoder.encode(model: wallet, continuation: continuation)
}
}
})
}

func putWallet(_ req: Request) async throws -> String {
let body = try req.content.decode(Mnemonic.self)

let mnemonic = body.mnemonic.components(separatedBy: .whitespaces)

return try await withCheckedThrowingContinuation({ (continuation: CheckedContinuation<String, Error>) in
switch context.securityService.restore(from: mnemonic) {
case .failure(let error):
continuation.resume(throwing: Abort(.init(statusCode: 500), reason: error.localizedDescription))

case .success(let result):
guard context.securityService.save(mnemonics: mnemonic, for: result) else {
continuation.resume(throwing: Abort(.init(statusCode: 500), reason: "Creation failed"))
return
}
context.walletStorage.set(wallet: result)
context.updateWalletContext()

getWallet() { result in
switch result {
case let .failure(error):
continuation.resume(throwing: Abort(.init(statusCode: 500), reason: error.localizedDescription))

case let .success(wallet):
Encoder.encode(model: wallet, continuation: continuation)
}
}
}
})
}

func postWallet(_ req: Request) async throws -> String {
context.resetWalletContext()

let address = context.walletStorage.walletAddress

guard let mnemonic = context.securityService.loadMnemonics(for: address) else {
throw Abort(.init(statusCode: 500), reason: "Failed to liad mnemonic")
}

return try await withCheckedThrowingContinuation({ (continuation: CheckedContinuation<String, Error>) in
getWallet() { result in
switch result {
case let .failure(error):
continuation.resume(throwing: Abort(.init(statusCode: 500), reason: error.localizedDescription))
case let .success(wallet):
let response = PostMnemonicResponse(wallet: wallet, mnemonic: mnemonic.joined(separator: " "))
Encoder.encode(model: response, continuation: continuation)
}
}
})
}

func deleteWallet(_ req: Request) -> Response {
context.resetWalletContext()
return Response()
}
}

// MARK: - Private

extension WalletRouteCollection {
private func getWallet(
completion: @escaping (Result<Wallet, Error>) -> Void
) {
fetchBalance() { result in
switch result {
case let .failure(error):
completion(.failure(error))

case let .success(balance):
let address = context.walletStorage.walletAddress
let wallet = Wallet(address: address, balance: balance, currency: ClientConstants.denom)

completion(.success(wallet))
}
}
}

private func fetchBalance(
completion: @escaping (Result<Int, Error>) -> Void
) {
context.walletService.fetchBalance { result in
switch result {
case let .failure(error):
completion(.failure(error))

case let .success(balances):
guard let balance = balances.first(where: { $0.denom == ClientConstants.denom }) else {
completion(.success(0))
return
}

guard let amount = Int(balance.amount) else {
// TODO: Call completion with error

return
}

completion(.success(amount))
}
}
}
}

0 comments on commit 9dd7779

Please sign in to comment.