gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-ios] branch master updated: Interface for getting exchange


From: gnunet
Subject: [taler-taler-ios] branch master updated: Interface for getting exchange details and accepting tos
Date: Tue, 16 Aug 2022 00:39:56 +0200

This is an automated email from the git hooks/post-receive script.

jonathan-buchanan pushed a commit to branch master
in repository taler-ios.

The following commit(s) were added to refs/heads/master by this push:
     new 92ef7a7  Interface for getting exchange details and accepting tos
92ef7a7 is described below

commit 92ef7a77119a3d38b5fe45b220abe55806eef52f
Author: Jonathan Buchanan <jonathan.russ.buchanan@gmail.com>
AuthorDate: Mon Aug 15 18:39:17 2022 -0400

    Interface for getting exchange details and accepting tos
---
 Taler.xcodeproj/project.pbxproj              |  44 ++++++++---
 Taler/Model/ExchangeManager.swift            |   5 ++
 Taler/Model/WithdrawModel.swift              | 107 +++++++++++++++++++++++++++
 Taler/Views/SettingsView.swift               | 100 ++++++++++++++++---------
 Taler/WalletBackend.swift                    |  10 ++-
 taler-swift/Sources/taler-swift/Amount.swift |  25 +++++--
 6 files changed, 238 insertions(+), 53 deletions(-)

diff --git a/Taler.xcodeproj/project.pbxproj b/Taler.xcodeproj/project.pbxproj
index cf2bdb7..3c5ceba 100644
--- a/Taler.xcodeproj/project.pbxproj
+++ b/Taler.xcodeproj/project.pbxproj
@@ -9,16 +9,17 @@
 /* Begin PBXBuildFile section */
                AB1F87C82887C94700AB82A0 /* TalerApp.swift in Sources */ = {isa 
= PBXBuildFile; fileRef = AB1F87C72887C94700AB82A0 /* TalerApp.swift */; };
                AB1F87CA2887D2F400AB82A0 /* ContentView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = AB1F87C92887D2F400AB82A0 /* ContentView.swift 
*/; };
+               AB69F9FA28AAED53005CCC2E /* WithdrawModel.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = AB69F9F928AAED53005CCC2E /* WithdrawModel.swift 
*/; };
                AB8C3807286A88A600E0A1DD /* WalletBackendTests.swift in Sources 
*/ = {isa = PBXBuildFile; fileRef = AB8C3806286A88A500E0A1DD /* 
WalletBackendTests.swift */; };
                ABB33065289C5BBB00668B42 /* ExchangeManager.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = ABB33064289C5BBB00668B42 /* 
ExchangeManager.swift */; };
                ABB33067289C658900668B42 /* BackendManager.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = ABB33066289C658900668B42 /* 
BackendManager.swift */; };
                ABB762AD2891059600E88634 /* SettingsView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = ABB762AC2891059600E88634 /* SettingsView.swift 
*/; };
                ABC13AA32859962800D23185 /* taler-swift in Frameworks */ = {isa 
= PBXBuildFile; productRef = ABC13AA22859962800D23185 /* taler-swift */; };
+               ABC4AC3B28A4619C0047A56F /* PendingView.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = ABC4AC3A28A4619C0047A56F /* PendingView.swift 
*/; };
+               ABC4AC3F28A473070047A56F /* PendingManager.swift in Sources */ 
= {isa = PBXBuildFile; fileRef = ABC4AC3E28A473070047A56F /* 
PendingManager.swift */; };
                ABE97B1D286D82BF00580772 /* AnyCodable in Frameworks */ = {isa 
= PBXBuildFile; productRef = ABE97B1C286D82BF00580772 /* AnyCodable */; };
                D112510026B12E3200D02E00 /* taler-wallet-embedded.js in 
CopyFiles */ = {isa = PBXBuildFile; fileRef = D11250FF26B12E3200D02E00 /* 
taler-wallet-embedded.js */; };
                D14AFD4324D232B500C51073 /* TalerUITests.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14AFD4224D232B500C51073 /* TalerUITests.swift 
*/; };
-               D14CE1B226C39E5D00612DBE /* BalanceRow.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14CE1B126C39E5D00612DBE /* BalanceRow.swift */; 
};
-               D14CE1B426C3A2D400612DBE /* BalanceList.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D14CE1B326C3A2D400612DBE /* BalanceList.swift 
*/; };
                D1AFF0F3268D59C200FBB744 /* libiono.a in Frameworks */ = {isa = 
PBXBuildFile; fileRef = D1AFF0F2268D59A500FBB744 /* libiono.a */; };
                D1D65B9826992E4600C1012A /* WalletBackend.swift in Sources */ = 
{isa = PBXBuildFile; fileRef = D1D65B9726992E4600C1012A /* WalletBackend.swift 
*/; };
 /* End PBXBuildFile section */
@@ -56,11 +57,14 @@
 /* Begin PBXFileReference section */
                AB1F87C72887C94700AB82A0 /* TalerApp.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = TalerApp.swift; 
sourceTree = "<group>"; };
                AB1F87C92887D2F400AB82A0 /* ContentView.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
ContentView.swift; sourceTree = "<group>"; };
+               AB69F9F928AAED53005CCC2E /* WithdrawModel.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
WithdrawModel.swift; sourceTree = "<group>"; };
                AB710490285995B6008B04F0 /* taler-swift */ = {isa = 
PBXFileReference; lastKnownFileType = text; path = "taler-swift"; sourceTree = 
SOURCE_ROOT; };
                AB8C3806286A88A500E0A1DD /* WalletBackendTests.swift */ = {isa 
= PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
WalletBackendTests.swift; sourceTree = "<group>"; };
                ABB33064289C5BBB00668B42 /* ExchangeManager.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
ExchangeManager.swift; sourceTree = "<group>"; };
                ABB33066289C658900668B42 /* BackendManager.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
BackendManager.swift; sourceTree = "<group>"; };
                ABB762AC2891059600E88634 /* SettingsView.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
SettingsView.swift; sourceTree = "<group>"; };
+               ABC4AC3A28A4619C0047A56F /* PendingView.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
PendingView.swift; sourceTree = "<group>"; };
+               ABC4AC3E28A473070047A56F /* PendingManager.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
PendingManager.swift; sourceTree = "<group>"; };
                D11250FF26B12E3200D02E00 /* taler-wallet-embedded.js */ = {isa 
= PBXFileReference; lastKnownFileType = sourcecode.javascript; path = 
"taler-wallet-embedded.js"; sourceTree = "<group>"; };
                D14AFD1D24D232B300C51073 /* Taler.app */ = {isa = 
PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; 
path = Taler.app; sourceTree = BUILT_PRODUCTS_DIR; };
                D14AFD2624D232B500C51073 /* Assets.xcassets */ = {isa = 
PBXFileReference; lastKnownFileType = folder.assetcatalog; path = 
Assets.xcassets; sourceTree = "<group>"; };
@@ -71,8 +75,6 @@
                D14AFD3E24D232B500C51073 /* TalerUITests.xctest */ = {isa = 
PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path 
= TalerUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
                D14AFD4224D232B500C51073 /* TalerUITests.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
TalerUITests.swift; sourceTree = "<group>"; };
                D14AFD4424D232B500C51073 /* Info.plist */ = {isa = 
PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; 
sourceTree = "<group>"; };
-               D14CE1B126C39E5D00612DBE /* BalanceRow.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
BalanceRow.swift; sourceTree = "<group>"; };
-               D14CE1B326C3A2D400612DBE /* BalanceList.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
BalanceList.swift; sourceTree = "<group>"; };
                D1AFF0F2268D59A500FBB744 /* libiono.a */ = {isa = 
PBXFileReference; lastKnownFileType = archive.ar; name = libiono.a; path = 
iono/compiled/x64/libiono.a; sourceTree = "<group>"; };
                D1D65B9726992E4600C1012A /* WalletBackend.swift */ = {isa = 
PBXFileReference; lastKnownFileType = sourcecode.swift; path = 
WalletBackend.swift; sourceTree = "<group>"; };
 /* End PBXFileReference section */
@@ -105,6 +107,27 @@
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
+               ABC4AC3C28A470C40047A56F /* Views */ = {
+                       isa = PBXGroup;
+                       children = (
+                               AB1F87C92887D2F400AB82A0 /* ContentView.swift 
*/,
+                               ABB762AC2891059600E88634 /* SettingsView.swift 
*/,
+                               ABC4AC3A28A4619C0047A56F /* PendingView.swift 
*/,
+                       );
+                       path = Views;
+                       sourceTree = "<group>";
+               };
+               ABC4AC3D28A4729E0047A56F /* Model */ = {
+                       isa = PBXGroup;
+                       children = (
+                               ABB33066289C658900668B42 /* 
BackendManager.swift */,
+                               ABB33064289C5BBB00668B42 /* 
ExchangeManager.swift */,
+                               ABC4AC3E28A473070047A56F /* 
PendingManager.swift */,
+                               AB69F9F928AAED53005CCC2E /* WithdrawModel.swift 
*/,
+                       );
+                       path = Model;
+                       sourceTree = "<group>";
+               };
                D14AFD1424D232B300C51073 = {
                        isa = PBXGroup;
                        children = (
@@ -131,17 +154,13 @@
                D14AFD1F24D232B300C51073 /* Taler */ = {
                        isa = PBXGroup;
                        children = (
+                               ABC4AC3D28A4729E0047A56F /* Model */,
+                               ABC4AC3C28A470C40047A56F /* Views */,
                                D1D65B9726992E4600C1012A /* WalletBackend.swift 
*/,
-                               D14CE1B126C39E5D00612DBE /* BalanceRow.swift */,
-                               D14CE1B326C3A2D400612DBE /* BalanceList.swift 
*/,
-                               AB1F87C92887D2F400AB82A0 /* ContentView.swift 
*/,
                                D14AFD2624D232B500C51073 /* Assets.xcassets */,
                                D14AFD2B24D232B500C51073 /* 
LaunchScreen.storyboard */,
                                D14AFD2E24D232B500C51073 /* Info.plist */,
                                AB1F87C72887C94700AB82A0 /* TalerApp.swift */,
-                               ABB762AC2891059600E88634 /* SettingsView.swift 
*/,
-                               ABB33064289C5BBB00668B42 /* 
ExchangeManager.swift */,
-                               ABB33066289C658900668B42 /* 
BackendManager.swift */,
                        );
                        path = Taler;
                        sourceTree = "<group>";
@@ -356,11 +375,12 @@
                                AB1F87C82887C94700AB82A0 /* TalerApp.swift in 
Sources */,
                                AB1F87CA2887D2F400AB82A0 /* ContentView.swift 
in Sources */,
                                ABB33067289C658900668B42 /* 
BackendManager.swift in Sources */,
+                               AB69F9FA28AAED53005CCC2E /* WithdrawModel.swift 
in Sources */,
                                ABB33065289C5BBB00668B42 /* 
ExchangeManager.swift in Sources */,
                                D1D65B9826992E4600C1012A /* WalletBackend.swift 
in Sources */,
                                ABB762AD2891059600E88634 /* SettingsView.swift 
in Sources */,
-                               D14CE1B426C3A2D400612DBE /* BalanceList.swift 
in Sources */,
-                               D14CE1B226C39E5D00612DBE /* BalanceRow.swift in 
Sources */,
+                               ABC4AC3B28A4619C0047A56F /* PendingView.swift 
in Sources */,
+                               ABC4AC3F28A473070047A56F /* 
PendingManager.swift in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/Taler/Model/ExchangeManager.swift 
b/Taler/Model/ExchangeManager.swift
index 003d2eb..ca4942e 100644
--- a/Taler/Model/ExchangeManager.swift
+++ b/Taler/Model/ExchangeManager.swift
@@ -15,6 +15,7 @@
  */
 
 import Foundation
+import taler_swift
 
 typealias ExchangeItem = WalletBackendListExchanges.ExchangeListItem
 
@@ -61,4 +62,8 @@ class ExchangeManager: ObservableObject {
         }
         self.loading = true
     }
+    
+    func withdraw(exchange: ExchangeItem) -> WithdrawModel {
+        return WithdrawModel(backend: self.backend, exchange: exchange)
+    }
 }
diff --git a/Taler/Model/WithdrawModel.swift b/Taler/Model/WithdrawModel.swift
new file mode 100644
index 0000000..f423923
--- /dev/null
+++ b/Taler/Model/WithdrawModel.swift
@@ -0,0 +1,107 @@
+/*
+ * This file is part of GNU Taler
+ * (C) 2022 Taler Systems S.A.
+ *
+ * GNU Taler is free software; you can redistribute it and/or modify it under 
the
+ * terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 3, or (at your option) any later version.
+ *
+ * GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
FOR
+ * A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * GNU Taler; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
+ */
+
+import Foundation
+import taler_swift
+
+class WithdrawModel: ObservableObject {
+    enum State {
+        case begin
+        case loading
+        case prompt(rawAmount: Amount,
+                    effectiveAmount: Amount)
+        case promptTOS(rawAmount: Amount,
+                       effectiveAmount: Amount,
+                       tos: String,
+                       etag: String)
+    }
+    
+    var backend: WalletBackend
+    let exchange: ExchangeItem
+    @Published var state: State
+    
+    init(backend: WalletBackend, exchange: ExchangeItem) {
+        self.backend = backend
+        self.exchange = exchange
+        self.state = .begin
+    }
+    
+    func getWithdrawDetails(amountStr: String) {
+        self.state = .loading
+        do {
+            let amount = try Amount(fromString: amountStr)
+            let req = 
WalletBackendGetWithdrawalDetailsForAmountRequest(exchangeBaseUrl: 
exchange.exchangeBaseUrl,
+                                                                        
amount: amount)
+            backend.sendFormattedRequest(request: req) { response, err in
+                // TODO: Use Combine instead.
+                DispatchQueue.main.async {
+                    if let res = response {
+                        if res.tosAccepted {
+                            self.state = .prompt(rawAmount: res.amountRaw, 
effectiveAmount: res.amountEffective)
+                        } else {
+                            self.getTos(rawAmount: res.amountRaw, 
effectiveAmount: res.amountEffective)
+                        }
+                    } else {
+                        self.state = .begin
+                        // TODO: Show error.
+                    }
+                }
+            }
+        } catch {
+            self.state = .begin
+            // TODO: Show error.
+        }
+    }
+    
+    private func getTos(rawAmount: Amount, effectiveAmount: Amount) {
+        self.state = .loading
+        let req = WalletBackendGetExchangeTermsOfService(exchangeBaseUrl: 
exchange.exchangeBaseUrl)
+        backend.sendFormattedRequest(request: req) { response, err in
+            // TODO: Use Combine instead
+            DispatchQueue.main.async {
+                if let res = response {
+                    self.state = .promptTOS(rawAmount: rawAmount,
+                                            effectiveAmount: effectiveAmount,
+                                            tos: res.content,
+                                            etag: res.currentEtag)
+                } else {
+                    self.state = .begin
+                    // TODO: Show error.
+                }
+            }
+        }
+    }
+    
+    func acceptTos() {
+        let oldState = self.state
+        self.state = .loading
+        switch oldState {
+        case .promptTOS(let rawAmount, let effectiveAmount, let tos, let etag):
+            let req = 
WalletBackendSetExchangeTermsOfServiceAccepted(exchangeBaseUrl: 
exchange.exchangeBaseUrl,
+                                                                     
acceptedEtag: etag)
+            backend.sendFormattedRequest(request: req) { response, err in
+                // TODO: Use Combine instead
+                DispatchQueue.main.async {
+                    self.state = oldState
+                    // TODO: Handle error.
+                }
+            }
+        default:
+            self.state = oldState
+            // TODO: Show error.
+        }
+    }
+}
diff --git a/Taler/Views/SettingsView.swift b/Taler/Views/SettingsView.swift
index 63c1f3d..bb25587 100644
--- a/Taler/Views/SettingsView.swift
+++ b/Taler/Views/SettingsView.swift
@@ -65,46 +65,80 @@ extension View {
     }
 }
 
-struct PromptWithdrawView: View {
-    let exchange: ExchangeItem
-    let amount: Amount
-    
-    var body: some View {
-        VStack {
-            Text("Fees or something")
-        }
-            .navigationTitle("Withdraw Digital Cash")
-    }
-}
-
 struct WithdrawView: View {
-    let exchange: ExchangeItem
+    @ObservedObject var model: WithdrawModel
     @State var amount: String = ""
     
     var body: some View {
-        VStack {
-            Button {
-                
-            } label: {
-                Text("Scan Taler QR Code")
+        switch model.state {
+        case .begin:
+            VStack {
+                Button {
+                    
+                } label: {
+                    Text("Scan Taler QR Code")
+                }
+                Text("Or transfer manually:")
+                HStack {
+                    TextField(model.exchange.currency, text: $amount)
+                }
+                Button {
+                    // TODO: Handle when the user inputs a non-valid amount
+                    model.getWithdrawDetails(amountStr: 
model.exchange.currency + ":" + amount)
+                } label: {
+                    Text("Check Fees")
+                }
             }
-            Text("Or transfer manually:")
-            HStack {
-                TextField(exchange.currency, text: $amount)
+                .navigationTitle("Withdraw")
+        case .loading:
+            ProgressView()
+                .navigationTitle("Withdraw")
+        case .prompt(let rawAmount, let effectiveAmount):
+            VStack {
+                Text("Withdraw")
+                Text(effectiveAmount.readableDescription)
+                Text("Chosen Amount")
+                Text(rawAmount.readableDescription)
+                Text("Fee")
+                Text("- \((try! rawAmount - 
effectiveAmount).readableDescription)")
+                Text("Exchange")
+                Text(model.exchange.name)
+                Button {
+                    // TODO
+                } label: {
+                    Text("Confirm Withdraw")
+                }
             }
-            NavigationLink {
-                // TODO: Handle when the user inputs a non-valid amount
-                /*do {
-                    let am = try Amount.init(fromString: exchange.currency + 
":" + amount)
-                    PromptWithdrawView(exchange: exchange, amount: am)
-                } catch {
-                    
-                }*/
-            } label: {
-                Text("Check Fees")
+                .navigationTitle("Withdraw")
+        case .promptTOS(let rawAmount, let effectiveAmount, let tos, let etag):
+            VStack {
+                Text("Withdraw")
+                Text(effectiveAmount.readableDescription)
+                Text("Chosen Amount")
+                Text(rawAmount.readableDescription)
+                Text("Fee")
+                Text("- \((try! rawAmount - 
effectiveAmount).readableDescription)")
+                Text("Exchange")
+                Text(model.exchange.name)
+                NavigationLink {
+                    VStack {
+                        ScrollView {
+                            Text(tos)
+                        }
+                        Button {
+                            model.acceptTos()
+                        } label: {
+                            Text("Accept Terms of Service")
+                        }
+
+                    }
+                        .navigationTitle("Review Terms of Service")
+                } label: {
+                    Text("Review Terms")
+                }
             }
+                .navigationTitle("Withdraw")
         }
-            .navigationTitle("Withdraw")
     }
 }
 
@@ -149,7 +183,7 @@ struct ExchangeListView: View {
                         Text("Currency: " + exchange.currency)
                             .frame(maxWidth: .infinity)
                         NavigationLink {
-                            WithdrawView(exchange: exchange)
+                            WithdrawView(model: 
exchangeManager.withdraw(exchange: exchange))
                         } label: {
                             Text("Withdraw")
                         }
diff --git a/Taler/WalletBackend.swift b/Taler/WalletBackend.swift
index a3f52e6..e440173 100644
--- a/Taler/WalletBackend.swift
+++ b/Taler/WalletBackend.swift
@@ -300,6 +300,11 @@ struct WalletBackendListExchanges: 
WalletBackendFormattedRequest {
         var exchangeBaseUrl: String
         var currency: String
         var paytoUris: [String]
+        
+        var name: String {
+            let url = URL(string: exchangeBaseUrl)!
+            return url.host!
+        }
     }
     
     struct Response: Decodable {
@@ -366,9 +371,9 @@ struct WalletBackendGetExchangeTermsOfService: 
WalletBackendFormattedRequest {
     }
     
     struct Response: Decodable {
-        var tos: String
+        var content: String
         var currentEtag: String
-        var acceptedEtag: String
+        var acceptedEtag: String?
     }
     
     func operation() -> String {
@@ -896,7 +901,6 @@ class WalletBackend: IonoMessageHandler {
     }
     
     func handleMessage(message: String) {
-        //print("got message: \(message)")
         do {
             guard let messageData = message.data(using: .utf8) else { throw 
WalletBackendError.deserializationError }
             let data = try JSONSerialization.jsonObject(with: messageData, 
options: .allowFragments) as? [String : Any]
diff --git a/taler-swift/Sources/taler-swift/Amount.swift 
b/taler-swift/Sources/taler-swift/Amount.swift
index e480575..62e1d7b 100644
--- a/taler-swift/Sources/taler-swift/Amount.swift
+++ b/taler-swift/Sources/taler-swift/Amount.swift
@@ -71,6 +71,21 @@ public class Amount: Codable, CustomStringConvertible {
         }
     }
     
+    /// The string representation of the amount, formatted as 
"`value`.`fraction` `currency`".
+    public var readableDescription: String {
+        if fraction == 0 {
+            return "\(value) \(currency)"
+        } else {
+            var frac = fraction
+            var fracStr = ""
+            while (frac > 0) {
+                fracStr += "\(frac / (Amount.fractionalBase / 10))"
+                frac = (frac * 10) % Amount.fractionalBase
+            }
+            return "\(value).\(fracStr) \(currency)"
+        }
+    }
+    
     /// Whether the value is valid. An amount is valid if and only if the 
currency is not empty and the value is less than the maximum allowed value.
     var valid: Bool {
         if currency.range(of: Amount.currencyRegex, options: 
.regularExpression) == nil {
@@ -188,7 +203,7 @@ public class Amount: Codable, CustomStringConvertible {
     /// - Throws:
     ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
     /// - Returns: The sum of `left` and `right`, normalized.
-    static func + (left: Amount, right: Amount) throws -> Amount {
+    public static func + (left: Amount, right: Amount) throws -> Amount {
         if left.currency != right.currency {
             throw AmountError.incompatibleCurrency
         }
@@ -208,7 +223,7 @@ public class Amount: Codable, CustomStringConvertible {
     /// - Throws:
     ///   - `AmountError.incompatibleCurrency` if `left` and `right` do not 
share the same currency.
     /// - Returns: The difference of `left` and `right`, normalized.
-    static func - (left: Amount, right: Amount) throws -> Amount {
+    public static func - (left: Amount, right: Amount) throws -> Amount {
         if left.currency != right.currency {
             throw AmountError.incompatibleCurrency
         }
@@ -232,7 +247,7 @@ public class Amount: Codable, CustomStringConvertible {
     ///   - dividend: The amount to divide.
     ///   - divisor: The scalar dividing `dividend`.
     /// - Returns: The quotient of `dividend` and `divisor`, normalized.
-    static func / (dividend: Amount, divisor: UInt32) throws -> Amount {
+    public static func / (dividend: Amount, divisor: UInt32) throws -> Amount {
         guard divisor != 0 else { throw AmountError.divideByZero }
         let result = try dividend.normalizedCopy()
         if (divisor == 1) {
@@ -251,7 +266,7 @@ public class Amount: Codable, CustomStringConvertible {
     ///   - amount: The amount to multiply.
     ///   - factor: The scalar multiplying `amount`.
     /// - Returns: The product of `amount` and `factor`, normalized.
-    static func * (amount: Amount, factor: UInt32) throws -> Amount {
+    public static func * (amount: Amount, factor: UInt32) throws -> Amount {
         let result = try amount.normalizedCopy()
         result.value = result.value * UInt64(factor)
         let fraction_tmp = UInt64(result.fraction) * UInt64(factor)
@@ -333,7 +348,7 @@ public class Amount: Codable, CustomStringConvertible {
     /// - Parameters:
     ///   - currency: The currency to use.
     /// - Returns: The zero amount for `currency`.
-    static func zero(currency: String) -> Amount {
+    public static func zero(currency: String) -> Amount {
         return Amount(currency: currency, value: 0, fraction: 0)
     }
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]