Replace the JavaScript mobile app with a native Swift iOS wallet
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import Foundation
|
||||
|
||||
/// Exact decimal <-> drops conversion (1 XRP = 1_000_000 drops) without
|
||||
/// floating point rounding errors.
|
||||
enum XRPAmount {
|
||||
static let dropsPerXRP: UInt64 = 1_000_000
|
||||
static let maxDrops: UInt64 = 100_000_000_000 * dropsPerXRP // 1e11 XRP
|
||||
|
||||
static func drops(fromXRP value: String) throws -> UInt64 {
|
||||
let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
guard !text.isEmpty, !text.hasPrefix("-"), !text.hasPrefix("+") else {
|
||||
throw XRPError.rpc("Enter a valid amount")
|
||||
}
|
||||
let parts = text.split(separator: ".", omittingEmptySubsequences: false)
|
||||
guard parts.count <= 2 else { throw XRPError.rpc("Enter a valid amount") }
|
||||
|
||||
let wholeText = parts[0].isEmpty ? "0" : String(parts[0])
|
||||
guard let whole = UInt64(wholeText) else { throw XRPError.rpc("Enter a valid amount") }
|
||||
|
||||
var fraction: UInt64 = 0
|
||||
if parts.count == 2 {
|
||||
let fractionText = String(parts[1])
|
||||
guard fractionText.count <= 6, fractionText.allSatisfy({ $0.isNumber }) else {
|
||||
throw XRPError.rpc("XRP supports at most 6 decimal places")
|
||||
}
|
||||
let padded = fractionText.padding(toLength: 6, withPad: "0", startingAt: 0)
|
||||
guard let parsed = UInt64(padded) else { throw XRPError.rpc("Enter a valid amount") }
|
||||
fraction = parsed
|
||||
}
|
||||
|
||||
let (wholeDrops, overflow) = whole.multipliedReportingOverflow(by: dropsPerXRP)
|
||||
guard !overflow else { throw XRPError.rpc("Amount is too large") }
|
||||
let (total, carry) = wholeDrops.addingReportingOverflow(fraction)
|
||||
guard !carry, total <= maxDrops else { throw XRPError.rpc("Amount is too large") }
|
||||
return total
|
||||
}
|
||||
|
||||
static func xrp(fromDrops drops: String) -> String {
|
||||
guard let value = UInt64(drops.trimmingCharacters(in: .whitespacesAndNewlines)) else {
|
||||
return "0"
|
||||
}
|
||||
return xrp(fromDrops: value)
|
||||
}
|
||||
|
||||
static func xrp(fromDrops value: UInt64) -> String {
|
||||
let whole = value / dropsPerXRP
|
||||
let fraction = value % dropsPerXRP
|
||||
if fraction == 0 { return String(whole) }
|
||||
var fractionText = String(format: "%06llu", fraction)
|
||||
while fractionText.hasSuffix("0") { fractionText.removeLast() }
|
||||
return "\(whole).\(fractionText)"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user