ADD: RON currency for widget

This commit is contained in:
Marcos Rodriguez Velez 2023-11-13 12:33:21 -04:00
parent 9d2da3e496
commit 0707667a55
No known key found for this signature in database
GPG Key ID: 6030B2F48CCE86D7
3 changed files with 147 additions and 77 deletions

View File

@ -68,6 +68,9 @@
B43D037B225847C500FBAA95 /* TransactionTableRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0375225847C500FBAA95 /* TransactionTableRow.swift */; };
B43D037C225847C500FBAA95 /* Wallet.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0376225847C500FBAA95 /* Wallet.swift */; };
B43D037D225847C500FBAA95 /* WalletInformation.swift in Sources */ = {isa = PBXBuildFile; fileRef = B43D0377225847C500FBAA95 /* WalletInformation.swift */; };
B451DAF22B027FD3008B561D /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B451DAF12B027FD3008B561D /* XMLParserDelegate.swift */; };
B451DAF32B027FD3008B561D /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B451DAF12B027FD3008B561D /* XMLParserDelegate.swift */; };
B451DAF42B027FD3008B561D /* XMLParserDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B451DAF12B027FD3008B561D /* XMLParserDelegate.swift */; };
B461B852299599F800E431AA /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = B461B851299599F800E431AA /* AppDelegate.mm */; };
B4EE583C226703320003363C /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B40D4E35225841ED00428FCC /* Assets.xcassets */; };
E5D4794B26781FC0007838C1 /* fiatUnits.json in Resources */ = {isa = PBXBuildFile; fileRef = 6DD410AD266CAF1F0087DE03 /* fiatUnits.json */; };
@ -283,6 +286,7 @@
B43D0376225847C500FBAA95 /* Wallet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Wallet.swift; sourceTree = "<group>"; };
B43D0377225847C500FBAA95 /* WalletInformation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WalletInformation.swift; sourceTree = "<group>"; };
B43D046E22584C1B00FBAA95 /* libRNWatch.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libRNWatch.a; sourceTree = BUILT_PRODUCTS_DIR; };
B451DAF12B027FD3008B561D /* XMLParserDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XMLParserDelegate.swift; sourceTree = "<group>"; };
B459EE96941AE09BCB547DC0 /* Pods-BlueWallet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BlueWallet.release.xcconfig"; path = "Pods/Target Support Files/Pods-BlueWallet/Pods-BlueWallet.release.xcconfig"; sourceTree = "<group>"; };
B461B850299599F800E431AA /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = BlueWallet/AppDelegate.h; sourceTree = "<group>"; };
B461B851299599F800E431AA /* AppDelegate.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = AppDelegate.mm; path = BlueWallet/AppDelegate.mm; sourceTree = "<group>"; };
@ -514,6 +518,7 @@
6D4AF18325D215D1009DD853 /* UserDefaultsExtension.swift */,
6D4AF18225D215D0009DD853 /* BlueWalletWatch-Bridging-Header.h */,
B40FC3F829CCD1AC0007EBAC /* SwiftTCPClient.swift */,
B451DAF12B027FD3008B561D /* XMLParserDelegate.swift */,
);
path = Shared;
sourceTree = "<group>";
@ -827,7 +832,7 @@
);
mainGroup = 83CBB9F61A601CBA00E9B192;
packageReferences = (
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */,
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */,
);
productRefGroup = 83CBBA001A601CBA00E9B192 /* Products */;
projectDirPath = "";
@ -1067,6 +1072,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
B451DAF22B027FD3008B561D /* XMLParserDelegate.swift in Sources */,
6D32C5C62596CE3A008C077C /* EventEmitter.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
B461B852299599F800E431AA /* AppDelegate.mm in Sources */,
@ -1089,6 +1095,7 @@
6DD410BB266CAF5C0087DE03 /* MarketView.swift in Sources */,
6DD410B5266CAF5C0087DE03 /* WidgetDataStore.swift in Sources */,
6DD410C0266CB1460087DE03 /* MarketWidget.swift in Sources */,
B451DAF42B027FD3008B561D /* XMLParserDelegate.swift in Sources */,
6DD410BA266CAF5C0087DE03 /* FiatUnit.swift in Sources */,
6DD410AF266CAF5C0087DE03 /* WalletInformationAndMarketWidget.swift in Sources */,
6DD410BF266CB13D0087DE03 /* Models.swift in Sources */,
@ -1124,6 +1131,7 @@
B40D4E632258425500428FCC /* ReceiveInterfaceController.swift in Sources */,
B43D0378225847C500FBAA95 /* WalletGradient.swift in Sources */,
6D4AF18425D215D1009DD853 /* UserDefaultsExtension.swift in Sources */,
B451DAF32B027FD3008B561D /* XMLParserDelegate.swift in Sources */,
B40D4E5E2258425500428FCC /* NumericKeypadInterfaceController.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -1830,7 +1838,7 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */ = {
6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/EFPrefix/EFQRCode.git";
requirement = {
@ -1843,7 +1851,7 @@
/* Begin XCSwiftPackageProductDependency section */
6DFC806F24EA0B6C007B8700 /* EFQRCode */ = {
isa = XCSwiftPackageProductDependency;
package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode.git" */;
package = 6DFC806E24EA0B6C007B8700 /* XCRemoteSwiftPackageReference "EFQRCode" */;
productName = EFQRCode;
};
/* End XCSwiftPackageProductDependency section */

View File

@ -39,89 +39,120 @@ class WidgetAPI {
urlString = "https://www.bitstamp.net/api/v2/ticker/btc\(endPointKey.lowercased())"
case "Coinbase":
urlString = "https://api.coinbase.com/v2/prices/BTC-\(endPointKey.uppercased())/buy"
case "CoinGecko":
case "CoinGecko":
urlString = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=\(endPointKey.lowercased())"
case "BNR":
urlString = "https://www.bnr.ro/nbrfxrates.xml"
default:
urlString = "https://api.coindesk.com/v1/bpi/currentprice/\(endPointKey).json"
}
guard let url = URL(string:urlString) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
let json = (try? JSONSerialization.jsonObject(with: dataResponse, options: .mutableContainers) as? Dictionary<String, Any>),
error == nil
else {
print(error?.localizedDescription ?? "Response Error")
completion(nil, error)
return
}
if source == "BNR" {
URLSession.shared.dataTask(with: url) { (data, response, error) in
if let error = error {
print("Error fetching data: \(error.localizedDescription)")
completion(nil, error)
return
}
var latestRateDataStore: WidgetDataStore?
switch source {
case "Yadio":
guard let rateDict = json[endPointKey] as? [String: Any],
let rateDouble = rateDict["price"] as? Double,
let lastUpdated = json["timestamp"] as? Int
else { break }
let unix = Double(lastUpdated / 1_000)
let lastUpdatedString = ISO8601DateFormatter().string(from: Date(timeIntervalSince1970: unix))
latestRateDataStore = WidgetDataStore(rate: String(rateDouble), lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "CoinGecko":
guard let rateDict = json["bitcoin"] as? [String: Any],
let rateDouble = rateDict[endPointKey.lowercased()] as? Double
else { break }
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: String(rateDouble), lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "YadioConvert":
guard let rateDict = json as? [String: Any],
let rateDouble = rateDict["rate"] as? Double,
let lastUpdated = json["timestamp"] as? Int
else { break }
let unix = Double(lastUpdated / 1_000)
let lastUpdatedString = ISO8601DateFormatter().string(from: Date(timeIntervalSince1970: unix))
latestRateDataStore = WidgetDataStore(rate: String(rateDouble), lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "Exir":
guard let rateDouble = json["last"] as? Double else { break }
let rateString = String(rateDouble)
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "Bitstamp":
guard let rateString = json["last"] as? String, let rateDouble = Double(rateString) else { break }
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "wazirx":
guard let tickerDict = json["ticker"] as? [String: Any],
let rateString = tickerDict["buy"] as? String,
let rateDouble = Double(rateString)
else { break }
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "Coinbase":
guard let data = json["data"] as? Dictionary<String, Any>,
let rateString = data["amount"] as? String,
let rateDouble = Double(rateString)
else { break }
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
default:
guard let bpi = json["bpi"] as? Dictionary<String, Any>,
let preferredCurrency = bpi[endPointKey] as? Dictionary<String, Any>,
let rateString = preferredCurrency["rate"] as? String,
let rateDouble = preferredCurrency["rate_float"] as? Double,
let time = json["time"] as? Dictionary<String, Any>,
let lastUpdatedString = time["updatedISO"] as? String
else { break }
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
}
guard let data = data else {
print("No data received")
completion(nil, nil)
return
}
if (latestRateDataStore == nil) {
completion(nil, CurrencyError())
return
}
completion(latestRateDataStore, nil)
}.resume()
// Parse XML data
let parser = XMLParser(data: data)
let delegate = BNRXMLParserDelegate()
parser.delegate = delegate
if parser.parse(), let rate = delegate.usdRate {
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
let latestRateDataStore = WidgetDataStore(rate: String(rate), lastUpdate: lastUpdatedString, rateDouble: rate)
completion(latestRateDataStore, nil)
} else {
print("Error parsing XML")
completion(nil, CurrencyError())
}
}.resume()
} else {
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let dataResponse = data,
let json = (try? JSONSerialization.jsonObject(with: dataResponse, options: .mutableContainers) as? Dictionary<String, Any>),
error == nil
else {
print(error?.localizedDescription ?? "Response Error")
completion(nil, error)
return
}
var latestRateDataStore: WidgetDataStore?
switch source {
case "Yadio":
guard let rateDict = json[endPointKey] as? [String: Any],
let rateDouble = rateDict["price"] as? Double,
let lastUpdated = json["timestamp"] as? Int
else { break }
let unix = Double(lastUpdated / 1_000)
let lastUpdatedString = ISO8601DateFormatter().string(from: Date(timeIntervalSince1970: unix))
latestRateDataStore = WidgetDataStore(rate: String(rateDouble), lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "CoinGecko":
guard let rateDict = json["bitcoin"] as? [String: Any],
let rateDouble = rateDict[endPointKey.lowercased()] as? Double
else { break }
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: String(rateDouble), lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "YadioConvert":
guard let rateDict = json as? [String: Any],
let rateDouble = rateDict["rate"] as? Double,
let lastUpdated = json["timestamp"] as? Int
else { break }
let unix = Double(lastUpdated / 1_000)
let lastUpdatedString = ISO8601DateFormatter().string(from: Date(timeIntervalSince1970: unix))
latestRateDataStore = WidgetDataStore(rate: String(rateDouble), lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "Exir":
guard let rateDouble = json["last"] as? Double else { break }
let rateString = String(rateDouble)
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "Bitstamp":
guard let rateString = json["last"] as? String, let rateDouble = Double(rateString) else { break }
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "wazirx":
guard let tickerDict = json["ticker"] as? [String: Any],
let rateString = tickerDict["buy"] as? String,
let rateDouble = Double(rateString)
else { break }
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
case "Coinbase":
guard let data = json["data"] as? Dictionary<String, Any>,
let rateString = data["amount"] as? String,
let rateDouble = Double(rateString)
else { break }
let lastUpdatedString = ISO8601DateFormatter().string(from: Date())
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
default:
guard let bpi = json["bpi"] as? Dictionary<String, Any>,
let preferredCurrency = bpi[endPointKey] as? Dictionary<String, Any>,
let rateString = preferredCurrency["rate"] as? String,
let rateDouble = preferredCurrency["rate_float"] as? Double,
let time = json["time"] as? Dictionary<String, Any>,
let lastUpdatedString = time["updatedISO"] as? String
else { break }
latestRateDataStore = WidgetDataStore(rate: rateString, lastUpdate: lastUpdatedString, rateDouble: rateDouble)
}
if (latestRateDataStore == nil) {
completion(nil, CurrencyError())
return
}
completion(latestRateDataStore, nil)
}.resume()
}
}
static func getUserPreferredCurrency() -> String {
@ -163,3 +194,5 @@ class WidgetAPI {
}
}

View File

@ -0,0 +1,29 @@
//
// XMLParserDelegate.swift
// BlueWallet
//
// Created by Marcos Rodriguez on 11/13/23.
// Copyright © 2023 BlueWallet. All rights reserved.
//
import Foundation
class BNRXMLParserDelegate: NSObject, XMLParserDelegate {
var usdRate: Double?
var currentElement = ""
var foundRate = false
func parser(_ parser: XMLParser, didStartElement elementName: String, namespaceURI: String?, qualifiedName qName: String?, attributes attributeDict: [String : String] = [:]) {
currentElement = elementName
if elementName == "Rate" && attributeDict["currency"] == "USD" {
foundRate = true
}
}
func parser(_ parser: XMLParser, foundCharacters string: String) {
if foundRate {
usdRate = Double(string)
foundRate = false
}
}
}