diff --git a/.gitignore b/.gitignore
index 9d12ca082..28b294117 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,3 +42,4 @@ litewallet-partner-api-ios
/partner-keys.plist
partner-keys.plist
GoogleService-Info.plist
+*.gpx
diff --git a/Dakar, Senegal.gpx b/Dakar, Senegal.gpx
new file mode 100644
index 000000000..25366a782
--- /dev/null
+++ b/Dakar, Senegal.gpx
@@ -0,0 +1,19 @@
+
+
+
+ new
+
+ gpx.studio
+
+
+
+
+ new
+ Cycling
+
+
+ 23.1
+
+
+
+
\ No newline at end of file
diff --git a/litewallet.xcodeproj/project.pbxproj b/litewallet.xcodeproj/project.pbxproj
index d8cc600ca..1e7078aed 100644
--- a/litewallet.xcodeproj/project.pbxproj
+++ b/litewallet.xcodeproj/project.pbxproj
@@ -76,7 +76,6 @@
24470E4723A6B6E900ADDA27 /* MockSeeds.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24470E4623A6B6E900ADDA27 /* MockSeeds.swift */; };
24670EAE2368EDE7006093E0 /* LFColorPalette.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 24670EAC2368EDE7006093E0 /* LFColorPalette.xcassets */; };
2485F7D023728C19005962F1 /* RELEASE_NOTES.md in Resources */ = {isa = PBXBuildFile; fileRef = 2485F7CE23728C19005962F1 /* RELEASE_NOTES.md */; };
- 248BFE2423AAD53700CE1A71 /* BuyTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 248BFE2323AAD53700CE1A71 /* BuyTableViewController.swift */; };
248BFE2623AB302200CE1A71 /* BuyWKWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 248BFE2523AB302200CE1A71 /* BuyWKWebViewController.swift */; };
2494037623AD35C000369261 /* BuyWKWebVCTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2494037523AD35C000369261 /* BuyWKWebVCTests.swift */; };
2494037823AD53B900369261 /* ChildViewTransitioningDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2494037723AD53B900369261 /* ChildViewTransitioningDelegate.swift */; };
@@ -89,8 +88,6 @@
24B523AD238A53DC0030594D /* BIP39Words.plist in Resources */ = {isa = PBXBuildFile; fileRef = 24B523AF238A53DC0030594D /* BIP39Words.plist */; };
24B8FAC4216128A000A155B1 /* PartnerData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B8FAC3216128A000A155B1 /* PartnerData.swift */; };
24B8FAD22162B10200A155B1 /* BuyCenterWebViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B8FAD12162B10200A155B1 /* BuyCenterWebViewController.swift */; };
- 24B8FAD72162B6FB00A155B1 /* bitrefill_index.html in Resources */ = {isa = PBXBuildFile; fileRef = 24B8FAD62162B6FB00A155B1 /* bitrefill_index.html */; };
- 24B8FADC2162D29100A155B1 /* general.css in Resources */ = {isa = PBXBuildFile; fileRef = 24B8FADB2162D29100A155B1 /* general.css */; };
24B8FADF2163C4D400A155B1 /* Currency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24B8FADE2163C4D400A155B1 /* Currency.swift */; };
24BA90C62410129E001E3825 /* FeeSelectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 24BA90C52410129E001E3825 /* FeeSelectorView.swift */; };
24D5F23822599C0B00225462 /* BarlowSemiCondensed-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 24D5F22522599C0900225462 /* BarlowSemiCondensed-Italic.ttf */; };
@@ -279,7 +276,6 @@
C350788C27DCB10700A50819 /* TextView+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C350788B27DCB10700A50819 /* TextView+Extension.swift */; };
C3543A27264AFE490005D17A /* LocaleChangeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3543A26264AFE490005D17A /* LocaleChangeView.swift */; };
C3543A29264AFE720005D17A /* LocaleChangeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3543A28264AFE720005D17A /* LocaleChangeViewModel.swift */; };
- C354C4632590059500675E0E /* TransactionsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C354C4622590059500675E0E /* TransactionsViewModel.swift */; };
C35ABD232574070A002BB9BB /* PartnersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35ABD222574070A002BB9BB /* PartnersView.swift */; };
C35ABD332574073F002BB9BB /* PartnersViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C35ABD322574073F002BB9BB /* PartnersViewModel.swift */; };
C35C1220293D464A0009022D /* FirebaseAnalytics in Frameworks */ = {isa = PBXBuildFile; productRef = C35C121F293D464A0009022D /* FirebaseAnalytics */; };
@@ -293,11 +289,15 @@
C36DBF6128F1988900FBCB24 /* LocalWebViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C36DBF6028F1988900FBCB24 /* LocalWebViewModel.swift */; };
C39443F9269DDAD3002703E9 /* LitewalletIconView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C39443F8269DDAD3002703E9 /* LitewalletIconView.swift */; };
C39A71472608CB4300E7B640 /* EmptyTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C39A71462608CB4300E7B640 /* EmptyTableViewCell.swift */; };
+ C3B419CB2BFCF14100EBD935 /* BuyHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B419CA2BFCF14100EBD935 /* BuyHostingController.swift */; };
+ C3B419CD2BFCF17600EBD935 /* BuyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B419CC2BFCF17600EBD935 /* BuyView.swift */; };
C3B7C3B9255EABBF00E98A64 /* SupportSafariViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B7C3B8255EABBF00E98A64 /* SupportSafariViewModel.swift */; };
C3B7C3EE255FF59200E98A64 /* ConstantsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3B7C3ED255FF59200E98A64 /* ConstantsTests.swift */; };
C3BD4A5325975C6000D97079 /* View+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3BD4A5225975C6000D97079 /* View+Extension.swift */; };
C3C8973825CD6B9300241FBE /* HostingTransactionCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C8973725CD6B9300241FBE /* HostingTransactionCell.swift */; };
C3D4379F2566EA3E00F423E1 /* LWActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3D4379E2566EA3E00F423E1 /* LWActivityIndicator.swift */; };
+ C3DBBE312BFE15AF00B95939 /* BuyTileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DBBE302BFE15AF00B95939 /* BuyTileView.swift */; };
+ C3E5A9052BFDEEF1002FBE04 /* BuyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E5A9042BFDEEF1002FBE04 /* BuyViewModel.swift */; };
C3E751C22AF689BA005571CA /* BRKeyExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E751C12AF689BA005571CA /* BRKeyExtension.swift */; };
C3E751C42AF68A50005571CA /* BRAddressExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E751C32AF68A50005571CA /* BRAddressExtension.swift */; };
C3E751C62AF68A8E005571CA /* BRTxInputExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3E751C52AF68A8E005571CA /* BRTxInputExtension.swift */; };
@@ -310,12 +310,14 @@
C3EFA9A12650807B005C59B5 /* LockScreenHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3EFA9A02650807B005C59B5 /* LockScreenHeaderView.swift */; };
C3EFA9A3265080FF005C59B5 /* LockScreenHeaderViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3EFA9A2265080FF005C59B5 /* LockScreenHeaderViewModel.swift */; };
C3EFA9A62651A808005C59B5 /* LockScreenTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3EFA9A52651A808005C59B5 /* LockScreenTests.swift */; };
- C3F7BCDC25FEC6AD00694C28 /* FailedAlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F7BCD925FEC6AC00694C28 /* FailedAlertView.swift */; };
- C3F7BCDE25FEC6AD00694C28 /* AlertFailureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F7BCDB25FEC6AC00694C28 /* AlertFailureView.swift */; };
C3F7BD0325FEC77100694C28 /* TransactionModalView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F7BD0225FEC77100694C28 /* TransactionModalView.swift */; };
+ C3F8F13C2C049A4A006C3211 /* LocaleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F8F13B2C049A4A006C3211 /* LocaleTests.swift */; };
+ C3F8F13E2C04C3A7006C3211 /* MoonpayHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F8F13D2C04C3A7006C3211 /* MoonpayHelper.swift */; };
+ C3F8F1422C04DEA2006C3211 /* NoBuyTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3F8F1412C04DEA2006C3211 /* NoBuyTabBarViewController.swift */; };
+ C3F8F1442C04F6BE006C3211 /* Dakar, Senegal.gpx in Resources */ = {isa = PBXBuildFile; fileRef = C3F8F1432C04F6BE006C3211 /* Dakar, Senegal.gpx */; };
+ C3F8F1462C05269A006C3211 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C3F8F1452C05269A006C3211 /* GoogleService-Info.plist */; settings = {ASSET_TAGS = ("initial-resources", ); }; };
C3FF4D5F28AC5A5800713139 /* SendAddressCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3FF4D5E28AC5A5800713139 /* SendAddressCellView.swift */; };
C3FF4D6128AC5AC100713139 /* SendAddressCellViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3FF4D6028AC5AC100713139 /* SendAddressCellViewModel.swift */; };
- C738969F2BEA3C0200029095 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = C738969E2BEA3C0200029095 /* GoogleService-Info.plist */; settings = {ASSET_TAGS = ("initial-resources", ); }; };
C73896A12BEA3C4900029095 /* partner-keys.plist in Resources */ = {isa = PBXBuildFile; fileRef = C73896A02BEA3C4900029095 /* partner-keys.plist */; settings = {ASSET_TAGS = ("initial-resources", ); }; };
CE03EC741EF256AC0038E3A8 /* SimpleUTXO.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE03EC731EF256AC0038E3A8 /* SimpleUTXO.swift */; };
CE0CD1591DBFBCF5004023DA /* ModalPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = CE0CD1581DBFBCF5004023DA /* ModalPresenter.swift */; };
@@ -751,7 +753,6 @@
2465873A23A5AAD100A32E9E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
24670EAC2368EDE7006093E0 /* LFColorPalette.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = LFColorPalette.xcassets; sourceTree = ""; };
2485F7CE23728C19005962F1 /* RELEASE_NOTES.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = RELEASE_NOTES.md; sourceTree = ""; };
- 248BFE2323AAD53700CE1A71 /* BuyTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyTableViewController.swift; sourceTree = ""; };
248BFE2523AB302200CE1A71 /* BuyWKWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyWKWebViewController.swift; sourceTree = ""; };
2494037523AD35C000369261 /* BuyWKWebVCTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyWKWebVCTests.swift; sourceTree = ""; };
2494037723AD53B900369261 /* ChildViewTransitioningDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChildViewTransitioningDelegate.swift; sourceTree = ""; };
@@ -766,8 +767,6 @@
24B523B0238A53E40030594D /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "zh-Hans"; path = "zh-Hans.lproj/BIP39Words.plist"; sourceTree = ""; };
24B8FAC3216128A000A155B1 /* PartnerData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartnerData.swift; sourceTree = ""; };
24B8FAD12162B10200A155B1 /* BuyCenterWebViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyCenterWebViewController.swift; sourceTree = ""; };
- 24B8FAD62162B6FB00A155B1 /* bitrefill_index.html */ = {isa = PBXFileReference; lastKnownFileType = text.html; path = bitrefill_index.html; sourceTree = ""; };
- 24B8FADB2162D29100A155B1 /* general.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = general.css; sourceTree = ""; };
24B8FADE2163C4D400A155B1 /* Currency.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = ""; };
24B9621723BA66CC00ECD938 /* pt */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/MainInterface.strings; sourceTree = ""; };
24B9621923BA66CE00ECD938 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/MainInterface.strings"; sourceTree = ""; };
@@ -1428,7 +1427,6 @@
C350788B27DCB10700A50819 /* TextView+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TextView+Extension.swift"; sourceTree = ""; };
C3543A26264AFE490005D17A /* LocaleChangeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocaleChangeView.swift; sourceTree = ""; };
C3543A28264AFE720005D17A /* LocaleChangeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocaleChangeViewModel.swift; sourceTree = ""; };
- C354C4622590059500675E0E /* TransactionsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TransactionsViewModel.swift; sourceTree = ""; };
C35ABD222574070A002BB9BB /* PartnersView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartnersView.swift; sourceTree = ""; };
C35ABD322574073F002BB9BB /* PartnersViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PartnersViewModel.swift; sourceTree = ""; };
C361F48128B368BC00E9798F /* AddressFieldView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddressFieldView.swift; sourceTree = ""; };
@@ -1439,6 +1437,8 @@
C39443F8269DDAD3002703E9 /* LitewalletIconView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LitewalletIconView.swift; sourceTree = ""; };
C39A71462608CB4300E7B640 /* EmptyTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmptyTableViewCell.swift; sourceTree = ""; };
C3ACF2DE25DED601008671D4 /* CHANGELOG.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = CHANGELOG.md; sourceTree = ""; };
+ C3B419CA2BFCF14100EBD935 /* BuyHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyHostingController.swift; sourceTree = ""; };
+ C3B419CC2BFCF17600EBD935 /* BuyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyView.swift; sourceTree = ""; };
C3B7C3B8255EABBF00E98A64 /* SupportSafariViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportSafariViewModel.swift; sourceTree = ""; };
C3B7C3ED255FF59200E98A64 /* ConstantsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConstantsTests.swift; sourceTree = ""; };
C3BD4A5225975C6000D97079 /* View+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+Extension.swift"; sourceTree = ""; };
@@ -1447,6 +1447,8 @@
C3BDB42826CC0338004DAE77 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = ""; };
C3C8973725CD6B9300241FBE /* HostingTransactionCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HostingTransactionCell.swift; sourceTree = ""; };
C3D4379E2566EA3E00F423E1 /* LWActivityIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LWActivityIndicator.swift; sourceTree = ""; };
+ C3DBBE302BFE15AF00B95939 /* BuyTileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyTileView.swift; sourceTree = ""; };
+ C3E5A9042BFDEEF1002FBE04 /* BuyViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuyViewModel.swift; sourceTree = ""; };
C3E751C12AF689BA005571CA /* BRKeyExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRKeyExtension.swift; sourceTree = ""; };
C3E751C32AF68A50005571CA /* BRAddressExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRAddressExtension.swift; sourceTree = ""; };
C3E751C52AF68A8E005571CA /* BRTxInputExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BRTxInputExtension.swift; sourceTree = ""; };
@@ -1459,12 +1461,14 @@
C3EFA9A02650807B005C59B5 /* LockScreenHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenHeaderView.swift; sourceTree = ""; };
C3EFA9A2265080FF005C59B5 /* LockScreenHeaderViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenHeaderViewModel.swift; sourceTree = ""; };
C3EFA9A52651A808005C59B5 /* LockScreenTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LockScreenTests.swift; sourceTree = ""; };
- C3F7BCD925FEC6AC00694C28 /* FailedAlertView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FailedAlertView.swift; sourceTree = ""; };
- C3F7BCDB25FEC6AC00694C28 /* AlertFailureView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertFailureView.swift; sourceTree = ""; };
C3F7BD0225FEC77100694C28 /* TransactionModalView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransactionModalView.swift; sourceTree = ""; };
+ C3F8F13B2C049A4A006C3211 /* LocaleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocaleTests.swift; sourceTree = ""; };
+ C3F8F13D2C04C3A7006C3211 /* MoonpayHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoonpayHelper.swift; sourceTree = ""; };
+ C3F8F1412C04DEA2006C3211 /* NoBuyTabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NoBuyTabBarViewController.swift; sourceTree = ""; };
+ C3F8F1432C04F6BE006C3211 /* Dakar, Senegal.gpx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "Dakar, Senegal.gpx"; sourceTree = ""; };
+ C3F8F1452C05269A006C3211 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
C3FF4D5E28AC5A5800713139 /* SendAddressCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendAddressCellView.swift; sourceTree = ""; };
C3FF4D6028AC5AC100713139 /* SendAddressCellViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SendAddressCellViewModel.swift; sourceTree = ""; };
- C738969E2BEA3C0200029095 /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; };
C73896A02BEA3C4900029095 /* partner-keys.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "partner-keys.plist"; sourceTree = ""; };
CE03EC731EF256AC0038E3A8 /* SimpleUTXO.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SimpleUTXO.swift; path = Models/SimpleUTXO.swift; sourceTree = ""; };
CE0CD1581DBFBCF5004023DA /* ModalPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ModalPresenter.swift; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
@@ -2038,6 +2042,7 @@
children = (
2427342B2381C21800E2D22F /* MainViewController.swift */,
C32DB42E26488CAA00017D26 /* TabBarViewController.swift */,
+ C3F8F1412C04DEA2006C3211 /* NoBuyTabBarViewController.swift */,
);
name = Main;
sourceTree = "";
@@ -2112,36 +2117,10 @@
path = Storyboards;
sourceTree = "";
};
- 24B8FAD52162B6D400A155B1 /* Bitrefill_Web */ = {
- isa = PBXGroup;
- children = (
- 24B8FAD62162B6FB00A155B1 /* bitrefill_index.html */,
- 24B8FADA2162CF7600A155B1 /* css */,
- 24B8FAD92162CF7000A155B1 /* js */,
- );
- name = Bitrefill_Web;
- sourceTree = "";
- };
- 24B8FAD92162CF7000A155B1 /* js */ = {
- isa = PBXGroup;
- children = (
- );
- name = js;
- sourceTree = "";
- };
- 24B8FADA2162CF7600A155B1 /* css */ = {
- isa = PBXGroup;
- children = (
- 24B8FADB2162D29100A155B1 /* general.css */,
- );
- name = css;
- sourceTree = "";
- };
24C516502158820E007CE038 /* Buy */ = {
isa = PBXGroup;
children = (
24B8FAD12162B10200A155B1 /* BuyCenterWebViewController.swift */,
- 248BFE2323AAD53700CE1A71 /* BuyTableViewController.swift */,
248BFE2523AB302200CE1A71 /* BuyWKWebViewController.swift */,
);
name = Buy;
@@ -2160,6 +2139,7 @@
isa = PBXGroup;
children = (
584E25002951DAAA005E0E8B /* LanguageSelectionTests.swift */,
+ C3F8F13B2C049A4A006C3211 /* LocaleTests.swift */,
);
path = "Language Selection Tests";
sourceTree = "";
@@ -2859,6 +2839,7 @@
75A2A7871DA5934300A983D8 = {
isa = PBXGroup;
children = (
+ C3F8F1432C04F6BE006C3211 /* Dakar, Senegal.gpx */,
C33685082BECE8B10069CBC7 /* PrivacyInfo.xcprivacy */,
75A2A7921DA5934300A983D8 /* litewallet */,
2465873723A5AAD100A32E9E /* litewalletTests */,
@@ -2916,7 +2897,6 @@
CE20C90F1DBE5B5100C8397A /* Views */,
CEBF33021DDE177F00348FC6 /* ViewModels */,
CE6D0E5A1E14BF8400137DF1 /* Models */,
- 24B8FAD52162B6D400A155B1 /* Bitrefill_Web */,
CE20C8F01DBAF6E100C8397A /* Extensions */,
22A9A9311DF61930000F0016 /* Platform */,
CEAA9E9C1DC2F8270066731D /* Fonts */,
@@ -2995,7 +2975,7 @@
isa = PBXGroup;
children = (
C73896A02BEA3C4900029095 /* partner-keys.plist */,
- C738969E2BEA3C0200029095 /* GoogleService-Info.plist */,
+ C3F8F1452C05269A006C3211 /* GoogleService-Info.plist */,
C3188E2526431E750008ADD1 /* Debug-GoogleService-Info.plist */,
);
name = LaunchDataResources;
@@ -3045,6 +3025,7 @@
C35ABD07257404C6002BB9BB /* SwiftUI+UIKit */ = {
isa = PBXGroup;
children = (
+ C3B419C92BFCF0C900EBD935 /* Buy */,
C3423C272B7905330051BD6D /* SafariServices+Extension.swift */,
C3423C292B7905330051BD6D /* SignupWebView.swift */,
C3423C282B7905330051BD6D /* SignupWebViewModel.swift */,
@@ -3057,7 +3038,6 @@
C3423C192B79039D0051BD6D /* LaunchCardHostingController.swift */,
C3FF4D5D28AC5A2000713139 /* Send */,
C3543A25264AFE190005D17A /* Settings */,
- C3F7BCD825FEC69B00694C28 /* Alerts */,
C32142E825C97CB900BECCD0 /* Transactions */,
C35ABD08257404D2002BB9BB /* Partners */,
C35ABD0925740518002BB9BB /* About */,
@@ -3087,6 +3067,17 @@
name = About;
sourceTree = "";
};
+ C3B419C92BFCF0C900EBD935 /* Buy */ = {
+ isa = PBXGroup;
+ children = (
+ C3B419CA2BFCF14100EBD935 /* BuyHostingController.swift */,
+ C3B419CC2BFCF17600EBD935 /* BuyView.swift */,
+ C3DBBE302BFE15AF00B95939 /* BuyTileView.swift */,
+ C3E5A9042BFDEEF1002FBE04 /* BuyViewModel.swift */,
+ );
+ name = Buy;
+ sourceTree = "";
+ };
C3B7C3EC255FF56100E98A64 /* Constants Tests */ = {
isa = PBXGroup;
children = (
@@ -3126,15 +3117,6 @@
path = "Lock Screen Tests";
sourceTree = "";
};
- C3F7BCD825FEC69B00694C28 /* Alerts */ = {
- isa = PBXGroup;
- children = (
- C3F7BCDB25FEC6AC00694C28 /* AlertFailureView.swift */,
- C3F7BCD925FEC6AC00694C28 /* FailedAlertView.swift */,
- );
- name = Alerts;
- sourceTree = "";
- };
C3FF4D5D28AC5A2000713139 /* Send */ = {
isa = PBXGroup;
children = (
@@ -3406,7 +3388,6 @@
CEBF33031DDE17A600348FC6 /* Transaction.swift */,
CE27F9581E2C8EA300F7F7F2 /* Amount.swift */,
CE124CF71E67A8E500DFA146 /* TransactionDirection.swift */,
- C354C4622590059500675E0E /* TransactionsViewModel.swift */,
);
name = ViewModels;
sourceTree = "";
@@ -3449,6 +3430,7 @@
CEBF292F1EF9D76F005C330A /* Environment.swift */,
CEE20C331EA5B4550086F724 /* ArticleIds.swift */,
CE3D4C581EF743EF0016B1C8 /* Functions.swift */,
+ C3F8F13D2C04C3A7006C3211 /* MoonpayHelper.swift */,
);
name = Constants;
sourceTree = "";
@@ -3730,7 +3712,6 @@
buildActionMask = 2147483647;
files = (
C3423C492B796D820051BD6D /* Ko.mp3 in Resources */,
- 24B8FAD72162B6FB00A155B1 /* bitrefill_index.html in Resources */,
75A2A79E1DA5934300A983D8 /* LaunchScreen.storyboard in Resources */,
C33685092BECE8B10069CBC7 /* PrivacyInfo.xcprivacy in Resources */,
C3423C3F2B796D820051BD6D /* Pt.mp3 in Resources */,
@@ -3741,7 +3722,6 @@
222319B21F279B3C00008F20 /* POSTBouncer.html in Resources */,
C73896A12BEA3C4900029095 /* partner-keys.plist in Resources */,
24670EAE2368EDE7006093E0 /* LFColorPalette.xcassets in Resources */,
- C738969F2BEA3C0200029095 /* GoogleService-Info.plist in Resources */,
24313CA523824F5800A83F69 /* Buy.storyboard in Resources */,
24D5F23B22599C0B00225462 /* BarlowSemiCondensed-Bold.ttf in Resources */,
24AF00FE221B331D00FF636F /* WarningConfirmation.storyboard in Resources */,
@@ -3755,6 +3735,7 @@
C3423C452B796D820051BD6D /* 中國人.mp3 in Resources */,
24D5F25022599C0B00225462 /* BarlowSemiCondensed-Light.ttf in Resources */,
C3423C472B796D820051BD6D /* Tr.mp3 in Resources */,
+ C3F8F1442C04F6BE006C3211 /* Dakar, Senegal.gpx in Resources */,
2494037F23AE0C7100369261 /* SyncProgressHeaderView.xib in Resources */,
C3188E2726431E750008ADD1 /* Debug-GoogleService-Info.plist in Resources */,
C3423C432B796D820051BD6D /* Uk.mp3 in Resources */,
@@ -3763,7 +3744,6 @@
24313C9F23824F5800A83F69 /* Animate.storyboard in Resources */,
C3423C442B796D820051BD6D /* Fr.mp3 in Resources */,
C3423C462B796D820051BD6D /* Id.mp3 in Resources */,
- 24B8FADC2162D29100A155B1 /* general.css in Resources */,
24313CA323824F5800A83F69 /* Send.storyboard in Resources */,
2485F7D023728C19005962F1 /* RELEASE_NOTES.md in Resources */,
24B523AD238A53DC0030594D /* BIP39Words.plist in Resources */,
@@ -3772,6 +3752,7 @@
C3423C402B796D820051BD6D /* De.mp3 in Resources */,
24DFCE6823B89CDE001F17F8 /* Settings.storyboard in Resources */,
24393B5C23C259400075218D /* Phrase.storyboard in Resources */,
+ C3F8F1462C05269A006C3211 /* GoogleService-Info.plist in Resources */,
C3423C422B796D820051BD6D /* coinflip.aiff in Resources */,
75A2A79B1DA5934300A983D8 /* Assets.xcassets in Resources */,
);
@@ -3904,6 +3885,7 @@
24470E4523A608A700ADDA27 /* AmountTests.swift in Sources */,
C3B7C3EE255FF59200E98A64 /* ConstantsTests.swift in Sources */,
24470E2323A5DB7D00ADDA27 /* WalletManagerTests.swift in Sources */,
+ C3F8F13C2C049A4A006C3211 /* LocaleTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -4013,7 +3995,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 248BFE2423AAD53700CE1A71 /* BuyTableViewController.swift in Sources */,
CEBF29301EF9D76F005C330A /* Environment.swift in Sources */,
C39A71472608CB4300E7B640 /* EmptyTableViewCell.swift in Sources */,
CEC6AA4D1DF0741100EE5AFD /* ModalDisplayable.swift in Sources */,
@@ -4074,12 +4055,12 @@
24016D9023F913C1006A6791 /* LWAnalytics.swift in Sources */,
C3C8973825CD6B9300241FBE /* HostingTransactionCell.swift in Sources */,
CE124CFC1E68932C00DFA146 /* FeeManager.swift in Sources */,
+ C3B419CB2BFCF14100EBD935 /* BuyHostingController.swift in Sources */,
CEE20C381EA5B4680086F724 /* Strings.swift in Sources */,
24AF0101221B349100FF636F /* WarningConfirmationViewController.swift in Sources */,
CE25BF8D1DF3B8A500BC67B6 /* InViewAlert.swift in Sources */,
22A9A9511DF61945000F0016 /* TxMetaData.swift in Sources */,
CE8CD8E11E31976800785E02 /* LoginViewController.swift in Sources */,
- C3F7BCDE25FEC6AD00694C28 /* AlertFailureView.swift in Sources */,
CEC6AA391DEE10BA00EE5AFD /* UINavigationController+Extension.swift in Sources */,
584E24FC2951D476005E0E8B /* NSNotificationNameExtension.swift in Sources */,
CECCE5B01E04AD7600D99448 /* DescriptionSendCell.swift in Sources */,
@@ -4094,9 +4075,11 @@
CEC6F8451E886723000795B8 /* PaymentRequest.swift in Sources */,
C3FF4D6128AC5AC100713139 /* SendAddressCellViewModel.swift in Sources */,
CE4C1CC81ED88B600063E184 /* URLController.swift in Sources */,
+ C3DBBE312BFE15AF00B95939 /* BuyTileView.swift in Sources */,
C30029EB25D019BC00F08C2B /* CopyButtonView.swift in Sources */,
24313C922382433700A83F69 /* LFModalReceiveQRViewController.swift in Sources */,
CE20C9171DBE6F2A00C8397A /* UIButton+BRWAdditions.swift in Sources */,
+ C3F8F1422C04DEA2006C3211 /* NoBuyTabBarViewController.swift in Sources */,
CEAA9E931DC110E70066731D /* WritePaperPhraseViewController.swift in Sources */,
CE92F9F41DED59E80046B516 /* UIView+AnimationAdditions.swift in Sources */,
24D5F26F225A5BEA00225462 /* ContainerViewController.swift in Sources */,
@@ -4109,12 +4092,12 @@
CE0CD1591DBFBCF5004023DA /* ModalPresenter.swift in Sources */,
CEE20C2F1EA3E5820086F724 /* BlinkingView.swift in Sources */,
CEC6AA441DEFCDE900EE5AFD /* ModalViewController.swift in Sources */,
- C3F7BCDC25FEC6AD00694C28 /* FailedAlertView.swift in Sources */,
24313C8423820C4B00A83F69 /* ReceiveLTCViewController.swift in Sources */,
CEEC70831E90C07C00EF788E /* Setting.swift in Sources */,
CE45C1F91E74B400002C3847 /* ManageWalletViewController.swift in Sources */,
CE92F9F01DED0C790046B516 /* PresentModalAnimator.swift in Sources */,
CEAA9E951DC1659F0066731D /* UILabel+BRWAdditions.swift in Sources */,
+ C3F8F13E2C04C3A7006C3211 /* MoonpayHelper.swift in Sources */,
CEBF292E1EF99E55005C330A /* LightWeightAlert.swift in Sources */,
CEBF32EE1DDBC30000348FC6 /* ShadowButton.swift in Sources */,
CEB909F71E5FE654001804DC /* EnterPhraseCollectionViewController.swift in Sources */,
@@ -4130,6 +4113,7 @@
CE27F9591E2C8EA300F7F7F2 /* Amount.swift in Sources */,
CE1280F61EEA855C00D27649 /* Date+Additions.swift in Sources */,
C350788C27DCB10700A50819 /* TextView+Extension.swift in Sources */,
+ C3B419CD2BFCF17600EBD935 /* BuyView.swift in Sources */,
CEEC708E1E954AAB00EF788E /* AboutCell.swift in Sources */,
22A9A9461DF61945000F0016 /* BRAPIClient.swift in Sources */,
24313C7E23820C1900A83F69 /* TransactionsViewController.swift in Sources */,
@@ -4146,7 +4130,6 @@
CEF3E8321DE55540007C0A9E /* CheckView.swift in Sources */,
CECCE5A91E0378FB00D99448 /* PinPadViewController.swift in Sources */,
584E24F32951C11A005E0E8B /* Localization.swift in Sources */,
- C354C4632590059500675E0E /* TransactionsViewModel.swift in Sources */,
C3423C1C2B7903CA0051BD6D /* LaunchView.swift in Sources */,
C32DAE0725925B7E003FC978 /* Color+Extension.swift in Sources */,
C36DBF5F28F18D2C00FBCB24 /* LocalWebView.swift in Sources */,
@@ -4244,6 +4227,7 @@
CE6D0F971DE8B73A00BD4BCF /* ModalTransitionDelegate.swift in Sources */,
C3E751C82AF68AEB005571CA /* UnsafeMutablePointerExtension.swift in Sources */,
C3BD4A5325975C6000D97079 /* View+Extension.swift in Sources */,
+ C3E5A9052BFDEEF1002FBE04 /* BuyViewModel.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -4502,7 +4486,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = litewallet/litewallet.entitlements;
- CURRENT_PROJECT_VERSION = 240519.1;
+ CURRENT_PROJECT_VERSION = 240527.6;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = ZV7987N2ZC;
EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = YES;
@@ -4512,6 +4496,7 @@
"$(inherited)",
);
INFOPLIST_FILE = "$(SRCROOT)/litewallet/Info.plist";
+ INFOPLIST_KEY_CFBundleDisplayName = Litewallet;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -4859,7 +4844,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = litewallet/litewallet.entitlements;
- CURRENT_PROJECT_VERSION = 240519.1;
+ CURRENT_PROJECT_VERSION = 240527.6;
DEVELOPMENT_TEAM = ZV7987N2ZC;
EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = YES;
FRAMEWORK_SEARCH_PATHS = (
@@ -4868,6 +4853,7 @@
"$(inherited)",
);
INFOPLIST_FILE = "$(SRCROOT)/litewallet/Info.plist";
+ INFOPLIST_KEY_CFBundleDisplayName = Litewallet;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
@@ -5000,7 +4986,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = litewallet/litewallet.entitlements;
- CURRENT_PROJECT_VERSION = 240519.1;
+ CURRENT_PROJECT_VERSION = 240527.6;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = ZV7987N2ZC;
EMBED_ASSET_PACKS_IN_PRODUCT_BUNDLE = NO;
@@ -5010,6 +4996,7 @@
"$(inherited)",
);
INFOPLIST_FILE = "$(SRCROOT)/litewallet/Info.plist";
+ INFOPLIST_KEY_CFBundleDisplayName = Litewallet;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.finance";
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
diff --git a/litewallet/AlertFailureView.swift b/litewallet/AlertFailureView.swift
deleted file mode 100644
index 6e55c10cf..000000000
--- a/litewallet/AlertFailureView.swift
+++ /dev/null
@@ -1,51 +0,0 @@
-import SwiftUI
-
-struct AlertFailureView: View {
- let alertFailureType: AlertFailureType
-
- let errorMessage: String
-
- init(alertFailureType: AlertFailureType, errorMessage: String) {
- self.alertFailureType = alertFailureType
- self.errorMessage = errorMessage
- }
-
- var body: some View {
- VStack {
- Text(alertFailureType.header)
- .foregroundColor(.white)
- .font(Font(UIFont.barlowBold(size: 18.0)))
- .padding()
-
- Divider()
- .frame(maxHeight: 1.0)
- .background(Color(UIColor.transparentWhite))
-
- Image(systemName: "nosign")
- .resizable()
- .aspectRatio(contentMode: .fit)
- .frame(width: 40,
- height: 40,
- alignment: /*@START_MENU_TOKEN@*/ .center/*@END_MENU_TOKEN@*/)
- .foregroundColor(.white)
- .padding()
-
- Text(self.errorMessage.localizedCapitalized)
- .foregroundColor(.white)
- .font(Font(UIFont.barlowSemiBold(size: 16.0)))
- .padding(.bottom, 60)
- }
- .background(Color(UIColor.gray))
- .cornerRadius(6.0)
- }
-}
-
-struct AlertFailureView_Previews: PreviewProvider {
- static let alert = AlertFailureType.failedResolution
- static let errorMessage = "Test Error"
-
- static var previews: some View {
- AlertFailureView(alertFailureType: alert, errorMessage: errorMessage)
- .environment(\.locale, .init(identifier: "en"))
- }
-}
diff --git a/litewallet/ApplicationController.swift b/litewallet/ApplicationController.swift
index 7e03eb85c..53cc08e21 100644
--- a/litewallet/ApplicationController.swift
+++ b/litewallet/ApplicationController.swift
@@ -1,5 +1,6 @@
import BackgroundTasks
import StoreKit
+import SwiftUI
import UIKit
let timeSinceLastExitKey = "TimeSinceLastExit"
@@ -73,6 +74,8 @@ class ApplicationController: Subscriber, Trackable {
}
private func setup() {
+ setupDefaults()
+ countLaunches()
setupRootViewController()
window?.makeKeyAndVisible()
offMainInitialization()
@@ -316,3 +319,40 @@ class ApplicationController: Subscriber, Trackable {
}
}
}
+
+extension ApplicationController {
+ func setupDefaults() {
+ if UserDefaults.standard.object(forKey: shouldRequireLoginTimeoutKey) == nil {
+ UserDefaults.standard.set(60.0 * 3.0, forKey: shouldRequireLoginTimeoutKey) // Default 3 min timeout
+ }
+ if UserDefaults.standard.object(forKey: hasSeenAnnounceView) == nil {
+ UserDefaults.standard.set(false, forKey: hasSeenAnnounceView) // Hasnt seen the Announce View
+ }
+ }
+
+ func countLaunches() {
+ if var launchNumber = UserDefaults.standard.object(forKey: numberOfLitewalletLaunches) as? Int {
+ launchNumber += 1
+ UserDefaults.standard.set(NSNumber(value: launchNumber), forKey: numberOfLitewalletLaunches)
+ if launchNumber == 5 {
+ if #available(iOS 14, *) {
+ if self.window != nil,
+ let scene = self.window?.windowScene
+ {
+ SKStoreReviewController.requestReview(in: scene)
+ }
+
+ } else {
+ SKStoreReviewController.requestReview()
+ }
+
+ LWAnalytics.logEventWithParameters(itemName: ._20200125_DSRR)
+ }
+ } else {
+ UserDefaults.standard.set(NSNumber(value: 1), forKey: numberOfLitewalletLaunches)
+ }
+ }
+
+ func willResignActive()
+ {}
+}
diff --git a/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/Contents.json b/litewallet/Assets.xcassets/Partners/moonpay-white-logo.imageset/Contents.json
similarity index 65%
rename from litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/Contents.json
rename to litewallet/Assets.xcassets/Partners/moonpay-white-logo.imageset/Contents.json
index abe66c16b..007d4b52e 100644
--- a/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/Contents.json
+++ b/litewallet/Assets.xcassets/Partners/moonpay-white-logo.imageset/Contents.json
@@ -1,17 +1,15 @@
{
"images" : [
{
- "filename" : "ud-Logo-Full-Light@1x.png",
"idiom" : "universal",
"scale" : "1x"
},
{
- "filename" : "ud-Logo-Full-Light@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
- "filename" : "ud-Logo-Full-Light@3x.png",
+ "filename" : "moonpay-white.png",
"idiom" : "universal",
"scale" : "3x"
}
diff --git a/litewallet/Assets.xcassets/Partners/moonpay-white-logo.imageset/moonpay-white.png b/litewallet/Assets.xcassets/Partners/moonpay-white-logo.imageset/moonpay-white.png
new file mode 100644
index 000000000..cd873e0a3
Binary files /dev/null and b/litewallet/Assets.xcassets/Partners/moonpay-white-logo.imageset/moonpay-white.png differ
diff --git a/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/Contents.json b/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/Contents.json
deleted file mode 100644
index 2f61daa27..000000000
--- a/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/Contents.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "simplexLogo@1x.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "simplexLogo@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/simplexLogo@1x.png b/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/simplexLogo@1x.png
deleted file mode 100644
index de62d20e2..000000000
Binary files a/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/simplexLogo@1x.png and /dev/null differ
diff --git a/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/simplexLogo@3x.png b/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/simplexLogo@3x.png
deleted file mode 100644
index ceffea6fb..000000000
Binary files a/litewallet/Assets.xcassets/Partners/simplexLogo.imageset/simplexLogo@3x.png and /dev/null differ
diff --git a/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/Contents.json b/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/Contents.json
deleted file mode 100644
index 9967ae866..000000000
--- a/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/Contents.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "simplexColor@1x.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "simplexColor@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
\ No newline at end of file
diff --git a/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/simplexColor@1x.png b/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/simplexColor@1x.png
deleted file mode 100644
index a5f2cfcdc..000000000
Binary files a/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/simplexColor@1x.png and /dev/null differ
diff --git a/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/simplexColor@3x.png b/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/simplexColor@3x.png
deleted file mode 100644
index 2aa7afe31..000000000
Binary files a/litewallet/Assets.xcassets/Partners/simplexLogoTypeColor.imageset/simplexColor@3x.png and /dev/null differ
diff --git a/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@1x.png b/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@1x.png
deleted file mode 100644
index 222a66f75..000000000
Binary files a/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@1x.png and /dev/null differ
diff --git a/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@2x.png b/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@2x.png
deleted file mode 100644
index 703d1468b..000000000
Binary files a/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@2x.png and /dev/null differ
diff --git a/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@3x.png b/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@3x.png
deleted file mode 100644
index 448f8c6b0..000000000
Binary files a/litewallet/Assets.xcassets/Partners/ud-color-logo.imageset/ud-Logo-Full-Light@3x.png and /dev/null differ
diff --git a/litewallet/BartyCrouch.swift b/litewallet/BartyCrouch.swift
index ee4ad5dde..af4fa82ad 100644
--- a/litewallet/BartyCrouch.swift
+++ b/litewallet/BartyCrouch.swift
@@ -3,25 +3,20 @@ import Foundation
enum BartyCrouch {
enum SupportedLanguage: String {
// TODO: remove unsupported languages from the following cases list & add any missing languages
- case arabic = "ar"
case chineseSimplified = "zh-Hans"
case chineseTraditional = "zh-Hant"
case english = "en"
case french = "fr"
case german = "de"
- case hindi = "hi"
case indonesian = "id"
case italian = "it"
case japanese = "ja"
case korean = "ko"
- case malay = "ms"
case portuguese = "pt"
case russian = "ru"
case spanish = "es"
- case danish = "da"
- case dutch = "nl"
- case swedish = "sv"
case turkey = "tr"
+ case ukrainian = "uk"
}
static func translate(key: String, translations: [SupportedLanguage: String], comment _: String? = nil) -> String {
diff --git a/litewallet/BuyHostingController.swift b/litewallet/BuyHostingController.swift
new file mode 100644
index 000000000..4e7426b77
--- /dev/null
+++ b/litewallet/BuyHostingController.swift
@@ -0,0 +1,51 @@
+import Foundation
+import SwiftUI
+
+/// Moonpay: List supported countries endpoint
+/// https://api.moonpay.com/v3/countries
+/// - Parameter alphaCode2Char: String
+/// - Parameter alphaCode3Char: String
+/// - Parameter isBuyAllowed: Bool
+/// - Parameter isSellAllowed: Bool
+/// - Parameter countryName: String (name)
+/// - Parameter isAllowedInCountry: Bool (isAllowed)
+/// ===================================
+/// Unused JSON parameters
+/// "isNftAllowed": false
+/// "isBalanceLedgerWithdrawAllowed": true,
+/// "isSelfServeHighRisk": true,
+/// "continent": "Asia",
+/// "supportedDocuments": [
+/// "passport",
+/// "driving_licence",
+/// "national_identity_card",
+/// "residence_permit",
+/// ],
+/// "suggestedDocument": "national_identity_card"
+/// - Returns: MoonpayCountryData
+public struct MoonpayCountryData: Codable, Hashable {
+ var alphaCode2Char: String
+ var alphaCode3Char: String
+ var isBuyAllowed: Bool
+ var isSellAllowed: Bool
+ var countryName: String
+ var isAllowedInCountry: Bool
+}
+
+class BuyHostingController: UIHostingController {
+ var contentView: BuyView
+
+ var isLoaded: Bool = false
+
+ init() {
+ let buyViewModel = BuyViewModel()
+ contentView = BuyView(viewModel: buyViewModel)
+
+ super.init(rootView: contentView)
+ }
+
+ @available(*, unavailable)
+ @MainActor dynamic required init?(coder _: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+}
diff --git a/litewallet/BuyTableViewController.swift b/litewallet/BuyTableViewController.swift
deleted file mode 100644
index a1a416dc9..000000000
--- a/litewallet/BuyTableViewController.swift
+++ /dev/null
@@ -1,96 +0,0 @@
-import SafariServices
-import SwiftUI
-import UIKit
-import WebKit
-
-class BuyTableViewController: UITableViewController, SFSafariViewControllerDelegate {
- @IBOutlet var bitrefillLogoImageView: UIImageView!
- @IBOutlet var bitrefillHeaderLabel: UILabel!
- @IBOutlet var bitrefillDetailsLabel: UILabel!
- @IBOutlet var bitrefillCellContainerView: UIView!
- @IBAction func didTapBitrefill(_: UIButton) {
- guard let url = URL(string: "https://www.bitrefill.com/?ref=bAshL935")
- else {
- return
- }
-
- let sfSafariVC = SFSafariViewController(url: url)
- sfSafariVC.delegate = self
- present(sfSafariVC, animated: true)
- }
-
- // MARK: Moonpay UI
-
- @IBOutlet var moonpayLogoImageView: UIImageView!
- @IBOutlet var moonpayHeaderLabel: UILabel!
- @IBOutlet var moonpayDetailsLabel: UILabel!
- @IBOutlet var moonpayCellContainerView: UIView!
- @IBOutlet var moonpaySegmentedControl: UISegmentedControl!
-
- @IBAction func didTapMoonpay(_: Any) {
- let timestamp = Int(Date().timeIntervalSince1970)
-
- let urlString = APIServer.baseUrl + "moonpay/buy" + "?address=\(currentWalletAddress)&idate=\(timestamp)&uid=\(uuidString)&code=\(currencyCode)"
-
- guard let url = URL(string: urlString) else { return }
-
- let sfSafariVC = SFSafariViewController(url: url)
- sfSafariVC.delegate = self
- present(sfSafariVC, animated: true)
- }
-
- private var currencyCode: String = "USD"
- private let uuidString: String = UIDevice.current.identifierForVendor?.uuidString ?? ""
- private let currentWalletAddress: String = WalletManager.sharedInstance.wallet?.receiveAddress ?? ""
-
- var store: Store?
- var walletManager: WalletManager?
-
- override func viewDidLoad() {
- super.viewDidLoad()
-
- let thinHeaderView = UIView()
- thinHeaderView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 1.0)
- thinHeaderView.backgroundColor = .white
- tableView.tableHeaderView = thinHeaderView
- tableView.tableFooterView = UIView()
-
- moonpaySegmentedControl.addTarget(self, action: #selector(didChangeCurrencyMoonpay), for: .valueChanged)
- moonpaySegmentedControl.selectedSegmentIndex = PartnerFiatOptions.usd.index
- moonpaySegmentedControl.selectedSegmentTintColor = .white
- moonpaySegmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.white], for: .normal)
- moonpaySegmentedControl.setTitleTextAttributes([NSAttributedString.Key.foregroundColor: UIColor.liteWalletBlue], for: .selected)
-
- setupWkVCData()
-
- LWAnalytics.logEventWithParameters(itemName: ._20191105_DTBT)
- }
-
- private func setupWkVCData() {
- let bitrefillData = Partner.partnerDataArray()[0]
- bitrefillLogoImageView.image = bitrefillData.logo
- bitrefillHeaderLabel.text = bitrefillData.headerTitle
- bitrefillDetailsLabel.text = bitrefillData.details
- bitrefillCellContainerView.layer.cornerRadius = 6.0
- bitrefillCellContainerView.layer.borderColor = UIColor.white.cgColor
- bitrefillCellContainerView.layer.borderWidth = 1.0
- bitrefillCellContainerView.clipsToBounds = true
-
- let moonpayData = Partner.partnerDataArray()[1]
- moonpayLogoImageView.image = moonpayData.logo
- moonpayHeaderLabel.text = moonpayData.headerTitle
- moonpayDetailsLabel.text = moonpayData.details
- moonpayCellContainerView.layer.cornerRadius = 6.0
- moonpayCellContainerView.layer.borderColor = UIColor.white.cgColor
- moonpayCellContainerView.layer.borderWidth = 1.0
- moonpayCellContainerView.clipsToBounds = true
- }
-
- @objc private func didChangeCurrencyMoonpay() {
- if let code = PartnerFiatOptions(rawValue: moonpaySegmentedControl.selectedSegmentIndex)?.description {
- currencyCode = code
- } else {
- print("Error: Code not found: \(moonpaySegmentedControl.selectedSegmentIndex)")
- }
- }
-}
diff --git a/litewallet/BuyTileView.swift b/litewallet/BuyTileView.swift
new file mode 100644
index 000000000..9ab8be84f
--- /dev/null
+++ b/litewallet/BuyTileView.swift
@@ -0,0 +1,45 @@
+import SwiftUI
+
+struct BuyTileView: View {
+ let codeCellHeight = 28.0
+ let codeCellWidth = 80.0
+ let smallPad = 3.0
+ let buttonRegularFont: Font = .barlowSemiBold(size: 18.0)
+
+ private var code: String
+
+ init(code: String) {
+ self.code = code
+ }
+
+ var body: some View {
+ ZStack {
+ RoundedRectangle(cornerRadius: 14.0)
+ .foregroundColor(.litewalletBlue)
+ .frame(width: codeCellWidth,
+ height: codeCellHeight,
+ alignment: .center)
+ .overlay {
+ RoundedRectangle(cornerRadius: 14.0)
+ .stroke(.white, lineWidth: 0.5)
+ .frame(width: codeCellWidth,
+ height: codeCellHeight,
+ alignment: .center)
+ }
+ Text(code)
+ .foregroundColor(.white)
+ .font(buttonRegularFont)
+ .frame(width: codeCellWidth,
+ height: codeCellHeight,
+ alignment: .center)
+ }
+ .frame(width: codeCellWidth,
+ height: codeCellHeight,
+ alignment: .center)
+ .padding(.all, smallPad)
+ }
+}
+
+#Preview {
+ BuyTileView(code: "USD")
+}
diff --git a/litewallet/BuyView.swift b/litewallet/BuyView.swift
new file mode 100644
index 000000000..2cbeec278
--- /dev/null
+++ b/litewallet/BuyView.swift
@@ -0,0 +1,176 @@
+import SafariServices
+import SwiftUI
+
+struct BuyView: View {
+ @ObservedObject
+ var viewModel: BuyViewModel
+
+ let paragraphFont: Font = .barlowSemiBold(size: 20.0)
+ let calloutFont: Font = .barlowLight(size: 12.0)
+ let smallCalloutFont: Font = .barlowLight(size: 10.0)
+
+ let genericPad = 25.0
+ let selectButtonHeight = 35.0
+ let smallPad = 6.0
+ let buttonHeight = 44.0
+ let pageHeight = 145.0
+ let hugeFont = Font.barlowBold(size: 30.0)
+ let buttonLightFont: Font = .barlowLight(size: 15.0)
+ let buttonRegularFont: Font = .barlowSemiBold(size: 18.0)
+ let appDelegate = UIApplication.shared.delegate as! AppDelegate
+
+ @State
+ private var shouldShowSafariVC = false
+
+ @State
+ private var didTapCopy = false
+ // https://en.wikipedia.org/wiki/Template:Most_traded_currencies
+ /// As of 1716366977
+ let rankedFiatCodes: [String] = ["USD", "EUR", "JPY", "GBP",
+ "CNY", "AUD", "CAD", "CHF",
+ "HKD", "SGD", "SEK", "NOK",
+ "NZD", "MXN", "TWD", "ZAR",
+ "BRL", "DKK", "PLN", "THB",
+ "ILS", "IDR", "CZK", "TRY",
+ "RON", "PEN"]
+
+ init(viewModel: BuyViewModel) {
+ self.viewModel = viewModel
+ }
+
+ var body: some View {
+ GeometryReader { geometry in
+
+ let width = geometry.size.width
+ let height = geometry.size.height
+
+ ZStack {
+ Color.liteWalletBlue.edgesIgnoringSafeArea(.all)
+ VStack {
+ Divider()
+ .frame(height: 1.0)
+ .background(.white)
+ .frame(maxWidth: .infinity, alignment: .center)
+ Text(S.BuyCenter.buyModalTitle.localize())
+ .font(hugeFont)
+ .multilineTextAlignment(.center)
+ .frame(maxWidth: .infinity, alignment: .center)
+ .frame(idealHeight: buttonHeight)
+ .foregroundColor(.white)
+ .padding([.leading, .trailing], genericPad)
+ .padding(.all, genericPad)
+
+ HStack {
+ VStack {
+ Picker(S.BuyCenter.buyDetail.localize() + " " + viewModel.receivingAddress,
+ selection: $viewModel.selectedCode) {
+ ForEach(rankedFiatCodes, id: \.self) {
+ BuyTileView(code: $0)
+ }
+ }
+ .pickerStyle(.wheel)
+ Spacer()
+ }
+
+ VStack {
+ Text(S.BuyCenter.buyDetail.localize())
+ .font(buttonRegularFont)
+ .multilineTextAlignment(.leading)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .frame(idealHeight: buttonHeight)
+ .foregroundColor(.white)
+ .padding([.leading, .trailing], genericPad)
+ .padding(.top, 0.0)
+ HStack {
+ Text(viewModel.receivingAddress)
+ .font(buttonLightFont)
+ .multilineTextAlignment(.leading)
+ .fixedSize(horizontal: false, vertical: true)
+ .frame(idealHeight: buttonHeight)
+ .foregroundColor(didTapCopy ? .litewalletBlue : .white)
+ .padding([.top, .bottom], smallPad)
+ Image(systemName: "doc.on.doc")
+ .foregroundColor(didTapCopy ? .litewalletBlue : .white)
+ }
+ .onTapGesture {
+ UIPasteboard.general.string = viewModel.receivingAddress
+ didTapCopy.toggle()
+ delay(0.2) {
+ didTapCopy.toggle()
+ }
+ }
+ .padding([.leading, .trailing], genericPad)
+ Button(action: {
+ if viewModel.receivingAddress != "" {
+ let timestamp = Int(Date().timeIntervalSince1970)
+ viewModel.urlString = APIServer.baseUrl + "moonpay/buy" + "?address=\(viewModel.receivingAddress)&idate=\(timestamp)&uid=\(viewModel.uuidString)&code=\(viewModel.selectedCode)"
+ self.shouldShowSafariVC = true
+ }
+
+ }) {
+ ZStack {
+ RoundedRectangle(cornerRadius: bigButtonCornerRadius)
+ .frame(width: width * 0.4, height: selectButtonHeight, alignment: .center)
+ .foregroundColor(.litewalletDarkBlue)
+
+ Text(S.BuyCenter.buyButtonTitle.localize() + " \(viewModel.selectedCode)")
+ .frame(width: width * 0.4, height: selectButtonHeight, alignment: .center)
+ .font(paragraphFont)
+ .foregroundColor(.white)
+ .overlay(
+ RoundedRectangle(cornerRadius: bigButtonCornerRadius)
+ .stroke(.white, lineWidth: 1.0)
+ )
+ }
+ }
+ .padding([.leading, .trailing], genericPad)
+ .sheet(isPresented: $shouldShowSafariVC) {
+ if let url = URL(string: viewModel.urlString) {
+ MoonpaySafariView(url: url)
+ }
+ }
+ }
+ }
+ .frame(height: height * 0.2
+ )
+
+ Divider()
+ .frame(height: 1.0)
+ .background(.white)
+ .frame(maxWidth: .infinity, alignment: .center)
+ HStack {
+ Text(S.BuyCenter.buyMoonpayDetail.localize())
+ .font(smallCalloutFont)
+ .multilineTextAlignment(.leading)
+ .frame(idealHeight: buttonHeight)
+ .foregroundColor(.white)
+ .padding(.leading, genericPad)
+ Image("moonpay-white-logo")
+ .resizable()
+ .aspectRatio(contentMode: .fit)
+ .frame(maxWidth: .infinity, alignment: .leading)
+ .frame(height: 14.0)
+ .opacity(0.8)
+ Spacer()
+ }
+ .frame(height: 20.0)
+ Spacer()
+ }
+ }
+ }
+ }
+}
+
+struct MoonpaySafariView: UIViewControllerRepresentable {
+ let url: URL
+
+ func makeUIViewController(context _: UIViewControllerRepresentableContext) -> SFSafariViewController {
+ return SFSafariViewController(url: url)
+ }
+
+ func updateUIViewController(_: SFSafariViewController, context _: UIViewControllerRepresentableContext) {}
+}
+
+#Preview {
+ BuyView(viewModel: BuyViewModel())
+}
diff --git a/litewallet/BuyViewModel.swift b/litewallet/BuyViewModel.swift
new file mode 100644
index 000000000..154874aa5
--- /dev/null
+++ b/litewallet/BuyViewModel.swift
@@ -0,0 +1,73 @@
+import Foundation
+import SwiftUI
+import UIKit
+
+class BuyViewModel: ObservableObject {
+ // MARK: - Combine Variables
+
+ @Published
+ var receivingAddress: String = ""
+
+ @Published
+ var urlString: String = ""
+
+ @Published
+ var selectedCode: String = "USD"
+
+ @Published
+ var uuidString: String = UIDevice.current.identifierForVendor?.uuidString ?? ""
+
+ init() {
+ receivingAddress = WalletManager.sharedInstance.wallet?.receiveAddress ?? ""
+ }
+
+ func fetchCurrenciesCountries(completion: @escaping ([MoonpayCountryData]) -> Void) {
+ let url = URL(string: "https://api.moonpay.com/v3/countries")!
+ var request = URLRequest(url: url)
+ request.httpMethod = "GET"
+ request.timeoutInterval = 10
+ request.allHTTPHeaderFields = ["accept": "application/json"]
+
+ let task = URLSession.shared.dataTask(with: request) { data, _, error in
+
+ if error == nil {
+ DispatchQueue.main.sync {
+ if let jsonData = try? JSONSerialization.jsonObject(with: data ?? Data(), options: []),
+ let jsonArray = jsonData as? [[String: Any]]
+ {
+ var dataArray: [MoonpayCountryData] = []
+
+ /// Filters allowed currencies and the top ranked currencies
+ for element in jsonArray {
+ if element["isBuyAllowed"] as? Bool == true &&
+ element["isAllowed"] as? Bool == true
+ {
+ let alpha2 = element["alpha2"] as? String
+ let alpha3 = element["alpha3"] as? String
+ let name = element["name"] as? String
+ let isBuyAllowed = element["isBuyAllowed"] as? Bool
+ let isSellAllowed = element["isSellAllowed"] as? Bool
+ let isAllowed = element["isAllowed"] as? Bool
+
+ let mpCountryData = MoonpayCountryData(alphaCode2Char: alpha2 ?? "",
+ alphaCode3Char: alpha3 ?? "",
+ isBuyAllowed: isBuyAllowed ?? false,
+ isSellAllowed: isSellAllowed ?? false,
+ countryName: name ?? "",
+ isAllowedInCountry: isAllowed ?? false)
+
+ dataArray.append(mpCountryData)
+ }
+ }
+ completion(dataArray)
+ }
+ }
+ } else {
+ let currencyError: [String: String] = ["error": error?.localizedDescription ?? ""]
+ LWAnalytics.logEventWithParameters(itemName: ._20200112_ERR, properties: currencyError)
+ completion([])
+ }
+ }
+ task.resume()
+ }
+}
diff --git a/litewallet/Constants/Constants+Events.swift b/litewallet/Constants/Constants+Events.swift
index a0fc630e9..d600fc195 100644
--- a/litewallet/Constants/Constants+Events.swift
+++ b/litewallet/Constants/Constants+Events.swift
@@ -237,4 +237,7 @@ enum CustomEvent: String {
/// Stop Push Notifications
case _20240510_SPN = "stopped_push_notifications"
+
+ /// Unsupported by Moonpay
+ case _20240527_UBM = "unsupported_by_moonpay"
}
diff --git a/litewallet/Constants/Strings.swift b/litewallet/Constants/Strings.swift
index 82a06f58f..019eae46e 100644
--- a/litewallet/Constants/Strings.swift
+++ b/litewallet/Constants/Strings.swift
@@ -132,17 +132,6 @@ enum S {
static let loadingRequest = Localization(key: "Send.loadingRequest", value: "Loading Request", comment: "Loading request activity view message")
static let insufficientFunds = Localization(key: "Send.insufficientFunds", value: "Insufficient Funds", comment: "Insufficient funds error")
static let barItemTitle = Localization(key: "Send.barItemTitle", value: "Send", comment: "Send Bar Item Title")
-
- enum UnstoppableDomains {
- static let placeholder = Localization(key: "Send.UnstoppableDomains.placeholder", value: "Enter a .crypto or .zil domain", comment: "Enter a .crypto,.zil domain")
- static let simplePlaceholder = Localization(key: "Send.UnstoppableDomains.simpleplaceholder", value: "Enter domain", comment: "Enter domain")
- static let enterA = Localization(key: "Send.UnstoppableDomains.enterA", value: "Enter a", comment: "Enter a")
- static let domain = Localization(key: "Send.UnstoppableDomains.domain", value: "domain", comment: "domain")
- static let lookup = Localization(key: "Send.UnstoppableDomains.lookup", value: "Lookup", comment: "Lookup")
- static let lookupFailureHeader = Localization(key: "Send.UnstoppableDomains.lookupFailureHeader", value: "LookupFailureHeader", comment: "lookupFailureHeader")
- static let lookupDomainError = Localization(key: "Send.UnstoppableDomains.lookupDomainError", value: "LookupDomainError", comment: "LookupDomainError")
- static let udSystemError = Localization(key: "Send.UnstoppableDomains.udSystemError", value: "UDSystemError", comment: "UDSystemError")
- }
}
enum Receive {
@@ -249,6 +238,11 @@ enum S {
enum BuyCenter {
static let title = Localization(key: "BuyCenter.title", value: "Buy Litecoin", comment: "Buy Center Title")
static let buyModalTitle = Localization(key: "BuyCenter.ModalTitle", value: "Buy Łitecoin", comment: "Buy Modal Title")
+ static let buyButtonTitle = Localization(key: "BuyCenter.buyButtonTitle", value: "Buy Ł with", comment: "Buy ButtonTitle")
+ static let buyDetail = Localization(key: "BuyCenter.buyDetail", value: "Ł will be sent to:", comment: "Buy ButtonTitle")
+ static let buyFiatDetail = Localization(key: "BuyCenter.buyFiatDetail", value: "Using:", comment: "Using fiat")
+ static let buyMoonpayDetail = Localization(key: "BuyCenter.buyMoonpayDetail", value: "Powered by:", comment: "Powered by")
+
enum Cells {
static let moonpayTitle = Localization(key: "BuyCenter.moonpayTitle", value: "Moonpay", comment: "Moonpay Title")
static let moonpayFinancialDetails = Localization(key: "BuyCenter.moonpayFinancialDetails", value: "• Point 1 XXXXX\n• Point 2 XXXXn• XXX Point 3", comment: "Moonpay buy financial details")
@@ -689,7 +683,6 @@ enum S {
static let processingTime = Localization(key: "Confirmation.processingTime", value: "Processing time: This transaction will take %1$@ minutes to process.", comment: "eg. Processing time: This transaction will take 10-30 minutes to process.")
static let processingAndDonationTime = Localization(key: "Confirmation.processingAndDonationTime", value: "Processing time: These transactions will take %1$@ minutes to process.", comment: "eg. Processing with Donation time: This transaction will take 10-30 minutes to process.")
static let amountLabel = Localization(key: "Confirmation.amountLabel", value: "Amount to Send:", comment: "Amount to Send: ($1.00)")
- static let donateLabel = Localization(key: "Confirmation.donateLabel", value: "Amount to Donate:", comment: "Amount to Donate: ($1.00)")
static let totalLabel = Localization(key: "Confirmation.totalLabel", value: "Total Cost:", comment: "Total Cost: ($5.00)")
static let amountDetailLabel = Localization(key: "Confirmation.amountDetailLabel", value: "Exchange details:", comment: "$53.09/L + 1.07%")
diff --git a/litewallet/Currency.swift b/litewallet/Currency.swift
index fccc34fff..8bfb58b01 100644
--- a/litewallet/Currency.swift
+++ b/litewallet/Currency.swift
@@ -15,7 +15,7 @@ enum PartnerFiatOptions: Int, CustomStringConvertible {
case cad
case aud
case idr
- case rub
+ case tur
case jpy
case eur
case gbp
@@ -30,7 +30,7 @@ enum PartnerFiatOptions: Int, CustomStringConvertible {
case .cad: return "CAD"
case .aud: return "AUD"
case .idr: return "IDR"
- case .rub: return "RUB"
+ case .tur: return "TRY"
case .jpy: return "JPY"
case .eur: return "EUR"
case .gbp: return "GBP"
@@ -43,7 +43,7 @@ enum PartnerFiatOptions: Int, CustomStringConvertible {
case .cad: return 0
case .aud: return 1
case .idr: return 2
- case .rub: return 3
+ case .tur: return 3
case .jpy: return 4
case .eur: return 5
case .gbp: return 6
diff --git a/litewallet/Extensions/UserDefaults+Additions.swift b/litewallet/Extensions/UserDefaults+Additions.swift
index bb595aa6e..7c618dad3 100644
--- a/litewallet/Extensions/UserDefaults+Additions.swift
+++ b/litewallet/Extensions/UserDefaults+Additions.swift
@@ -53,7 +53,7 @@ extension UserDefaults {
} else {
currencyCode = defaults.string(forKey: defaultCurrencyCodeKey)!
}
- let acceptedCurrencyCodes = ["USD", "EUR", "JPY", "BGN", "CZK", "DKK", "GBP", "HUF", "PLN", "RON", "SEK", "CHF", "NOK", "HRK", "RUB", "TRY", "AUD", "BRL", "CAD", "CNY", "HKD", "IDR", "ILS", "INR", "KRW", "MXN", "MYR", "NZD", "PHP", "SDG", "THB", "ZAR"]
+ let acceptedCurrencyCodes = ["USD", "EUR", "JPY", "BGN", "CZK", "DKK", "GBP", "HUF", "PLN", "RON", "SEK", "CHF", "NOK", "HRK", "TRY", "AUD", "BRL", "CAD", "CNY", "HKD", "IDR", "ILS", "INR", "KRW", "MXN", "MYR", "NZD", "PHP", "SDG", "THB", "ZAR"]
if !(acceptedCurrencyCodes.contains(currencyCode)) {
return "USD"
diff --git a/litewallet/FailedAlertView.swift b/litewallet/FailedAlertView.swift
deleted file mode 100644
index 44cfee369..000000000
--- a/litewallet/FailedAlertView.swift
+++ /dev/null
@@ -1,38 +0,0 @@
-//
-// FailedAlertView.swift
-// loafwallet
-//
-// Created by Kerry Washington on 1/29/21.
-// Copyright © 2021 Litecoin Foundation. All rights reserved.
-//
-import UIKit
-
-enum AlertFailureType {
- case failedResolution
-
- var header: String {
- switch self {
- case .failedResolution:
- return S.Send.UnstoppableDomains.lookupFailureHeader.localize()
- }
- }
-
- var subheader: String {
- switch self {
- case .failedResolution:
- return S.SecurityAlerts.resolvedSuccessSubheader.localize()
- }
- }
-
- var icon: UIView {
- return CheckView()
- }
-}
-
-extension AlertFailureType: Equatable {}
-
-func == (lhs: AlertFailureType, rhs: AlertFailureType) -> Bool {
- switch (lhs, rhs) {
- case (.failedResolution, .failedResolution): return true
- }
-}
diff --git a/litewallet/ForgotView.swift b/litewallet/ForgotView.swift
index 56647869f..8b1378917 100644
--- a/litewallet/ForgotView.swift
+++ b/litewallet/ForgotView.swift
@@ -1,115 +1 @@
-import SwiftUI
-// DEV: To be removed in following issue https://github.com/litecoin-foundation/litewallet-ios/issues/177
-struct ForgotAlertView: View where Presenting: View {
- // MARK: - Combine Variables
-
- @ObservedObject
- var viewModel = ForgotAlertViewModel()
-
- @Binding
- var isShowingForgot: Bool
-
- @State
- var email = ""
-
- let presenting: Presenting
-
- var mainMessage: String
-
- @State
- var detailMessage: String = S.LitecoinCard.resetPasswordDetail.localize()
-
- @State
- var didCheckEmailAddress = false
-
- var body: some View {
- GeometryReader { (_: GeometryProxy) in
- HStack {
- Spacer()
- ZStack {
- self.presenting.disabled(isShowingForgot)
- VStack {
- // Dismiss button
- Button(action: {
- viewModel.shouldDismissView {
- self.isShowingForgot.toggle()
- UIApplication.shared.endEditing()
- }
-
- }) {
- Image("whiteCross")
- .resizable()
- .aspectRatio(contentMode: .fit)
- .frame(width: 15,
- height: 15)
- }
- .frame(minWidth: 0, maxWidth: .infinity, alignment: .trailing)
-
- Text(S.LitecoinCard.forgotPassword.localize())
- .font(Font(UIFont.barlowSemiBold(size: 21.0)))
- .padding(.bottom, 8)
- .foregroundColor(Color.white)
-
- Text(detailMessage)
- .font(Font(UIFont.barlowRegular(size: 18.0)))
- .foregroundColor(Color.white)
- .multilineTextAlignment(.leading)
- .padding(.bottom, 12)
- .padding([.leading, .trailing], 8)
- .onReceive(viewModel.$detailMessage, perform: { updatedMessage in
- detailMessage = updatedMessage
- })
-
- TextField(S.Receive.emailButton.localize(), text: $email)
- .font(Font(UIFont.barlowMedium(size: 16.0)))
- .textFieldStyle(RoundedBorderTextFieldStyle())
- .keyboardType(.emailAddress)
- .autocapitalization(.none)
- .disableAutocorrection(true)
- .padding(.all, 20)
-
- HStack {
- // Reset password button
- Button(action: {
- withAnimation {
- viewModel.emailString = email
- viewModel.resetPassword {
- DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
- self.isShowingForgot.toggle()
- UIApplication.shared.endEditing()
- didCheckEmailAddress = true
- detailMessage = S.LitecoinCard.resetPasswordDetail.localize()
- }
- }
- }
- }) {
- Text(S.LitecoinCard.resetPassword.localize())
- .frame(minWidth: 0, maxWidth: .infinity)
- .font(Font(UIFont.barlowBold(size: 20.0)))
- .foregroundColor(Color.white)
- .padding(.all, 8)
- .overlay(
- RoundedRectangle(cornerRadius: 4)
- .stroke(Color(UIColor.white), lineWidth: 1)
- )
- .padding([.leading, .trailing], 20)
- .padding([.top, .bottom], 10)
- }
- }
- }
- .padding()
- .overlay(
- RoundedRectangle(cornerRadius: 8)
- .stroke(Color.gray, lineWidth: 1.5)
- )
- .background(Color(UIColor.liteWalletBlue))
- .cornerRadius(8)
- .shadow(color: .black, radius: 10, x: 5, y: 5)
- .opacity(self.isShowingForgot ? 1 : 0)
- }
- Spacer()
- }
- }
- }
-}
diff --git a/litewallet/MainViewController.swift b/litewallet/MainViewController.swift
index 2026678d1..78a3baae1 100644
--- a/litewallet/MainViewController.swift
+++ b/litewallet/MainViewController.swift
@@ -86,29 +86,68 @@ class MainViewController: UIViewController, Subscriber, LoginViewControllerDeleg
func didUnlockLogin() {
let hasSeenAnnounce = UserDefaults.standard.bool(forKey: hasSeenAnnounceView)
- guard let tabVC = UIStoryboard(name: "Main", bundle: nil)
- .instantiateViewController(withIdentifier: "TabBarViewController")
- as? TabBarViewController
- else {
- NSLog("TabBarViewController not intialized")
- return
+ // Check Locale - Assume unsupported if nil
+ let currentLocaleCountry = Locale.current.regionCode ?? "RU"
+ var userIsMoonPaySupported = true
+ for unsupportedLocale in UnsupportedCountries.allCases {
+ let truncatedCode = unsupportedLocale.localeCode.suffix(2)
+
+ if currentLocaleCountry == truncatedCode {
+ userIsMoonPaySupported = false
+ let unsupportedDict: [String: String] = ["unsupported_country": unsupportedLocale.localeCode]
+ LWAnalytics.logEventWithParameters(itemName: ._20240527_UBM, properties: unsupportedDict)
+ break
+ }
}
- tabVC.store = store
- tabVC.walletManager = walletManager
+ if userIsMoonPaySupported {
+ guard let tabVC = UIStoryboard(name: "Main", bundle: nil)
+ .instantiateViewController(withIdentifier: "TabBarViewController")
+ as? TabBarViewController
+ else {
+ NSLog("TabBarViewController not intialized")
+ return
+ }
- addChildViewController(tabVC, layout: {
- tabVC.view.constrain(toSuperviewEdges: nil)
- tabVC.view.alpha = 0
- tabVC.view.layoutIfNeeded()
- })
+ tabVC.store = store
+ tabVC.walletManager = walletManager
+ tabVC.userIsMoonPaySupported = userIsMoonPaySupported
- UIView.animate(withDuration: 0.3, delay: 0.1, options: .transitionCrossDissolve, animations: {
- tabVC.view.alpha = 1
- }) { _ in
- NSLog("US MainView Controller presented")
- }
+ addChildViewController(tabVC, layout: {
+ tabVC.view.constrain(toSuperviewEdges: nil)
+ tabVC.view.alpha = 0
+ tabVC.view.layoutIfNeeded()
+ })
+ UIView.animate(withDuration: 0.3, delay: 0.1, options: .transitionCrossDissolve, animations: {
+ tabVC.view.alpha = 1
+ }) { _ in
+ NSLog("US MainView Controller presented")
+ }
+ } else {
+ guard let noBuyTabVC = UIStoryboard(name: "Main", bundle: nil)
+ .instantiateViewController(withIdentifier: "NoBuyTabBarViewController")
+ as? NoBuyTabBarViewController
+ else {
+ NSLog("TabBarViewController not intialized")
+ return
+ }
+
+ noBuyTabVC.store = store
+ noBuyTabVC.walletManager = walletManager
+
+ addChildViewController(noBuyTabVC, layout: {
+ noBuyTabVC.view.constrain(toSuperviewEdges: nil)
+ noBuyTabVC.view.alpha = 0
+ noBuyTabVC.view.layoutIfNeeded()
+ })
+
+ UIView.animate(withDuration: 0.3, delay: 0.1, options: .transitionCrossDissolve, animations: {
+ noBuyTabVC.view.alpha = 1
+ }) { _ in
+ NSLog("US MainView Controller presented")
+ }
+ }
delay(4.0) {
self.appDelegate.pushNotifications.registerForRemoteNotifications()
}
diff --git a/litewallet/ModalPresenter.swift b/litewallet/ModalPresenter.swift
index f23fe2aed..8a6ef7f5f 100644
--- a/litewallet/ModalPresenter.swift
+++ b/litewallet/ModalPresenter.swift
@@ -209,42 +209,6 @@ class ModalPresenter: Subscriber, Trackable {
})
}
- private func presentFailureAlert(_: AlertFailureType,
- errorMessage: String,
- completion: @escaping () -> Void)
- {
- let hostingViewController = UIHostingController(rootView: AlertFailureView(alertFailureType: .failedResolution,
- errorMessage: errorMessage))
-
- guard let window = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first,
- let failureAlertView = hostingViewController.view else { return }
- let size = window.bounds.size
- window.addSubview(failureAlertView)
-
- let topConstraint = failureAlertView.constraint(.top, toView: window, constant: size.height)
- failureAlertView.constrain([
- failureAlertView.constraint(.width, constant: size.width),
- failureAlertView.constraint(.height, constant: alertHeight + 50.0),
- failureAlertView.constraint(.leading, toView: window, constant: nil),
- topConstraint,
- ])
- window.layoutIfNeeded()
-
- UIView.spring(0.6, animations: {
- topConstraint?.constant = size.height - self.alertHeight
- window.layoutIfNeeded()
- }, completion: { _ in
- UIView.spring(0.6, delay: 5.0, animations: {
- topConstraint?.constant = size.height
- window.layoutIfNeeded()
- }, completion: { _ in
- // TODO: - Make these callbacks generic
- completion()
- failureAlertView.removeFromSuperview()
- })
- })
- }
-
private func rootModalViewController(_ type: RootModal) -> UIViewController? {
switch type {
case .none:
@@ -322,14 +286,6 @@ class ModalPresenter: Subscriber, Trackable {
sendVC.onPublishSuccess = { [weak self] in
self?.presentAlert(.sendSuccess, completion: {})
}
-
- sendVC.onResolvedSuccess = { [weak self] in
- self?.presentAlert(.resolvedSuccess, completion: {})
- }
-
- sendVC.onResolutionFailure = { [weak self] failureMessage in
- self?.presentFailureAlert(.failedResolution, errorMessage: failureMessage, completion: {})
- }
return root
}
diff --git a/litewallet/MoonpayHelper.swift b/litewallet/MoonpayHelper.swift
new file mode 100644
index 000000000..35e76a515
--- /dev/null
+++ b/litewallet/MoonpayHelper.swift
@@ -0,0 +1,68 @@
+import Foundation
+
+/// 14 Languages
+enum UnsupportedCountries: Int, CaseIterable, Equatable, Identifiable {
+ case Afghanistan = 0
+ case Barbados
+ case Belarus
+ case BurkinaFaso
+ case China
+ case Iceland
+ case Iraq
+ case Jamaica
+ case Japan
+ case Kosovo
+ case Liberia
+ case Macao
+ case Malaysia
+ case Malta
+ case Mongolia
+ case Morocco
+ case Myanmar
+ case Nicaragua
+ case Pakistan
+ case Panama
+ case Russia
+ case Senegal
+ case DemocraticRepCongo
+ case Uganda
+ case Ukraine
+ case Venezuela
+ case Yemen
+ case Zimbabwe
+
+ var id: UnsupportedCountries { self }
+
+ var localeCode: String {
+ switch self {
+ case .Afghanistan: return "fa_AF"
+ case .Barbados: return "en_BB"
+ case .Belarus: return "be_BY"
+ case .BurkinaFaso: return "fr_BF"
+ case .China: return "zh_CN"
+ case .Iceland: return "is_IS"
+ case .Iraq: return "ar_IQ"
+ case .Jamaica: return "en_JM"
+ case .Japan: return "jp_JP"
+ case .Kosovo: return "sq_XK"
+ case .Liberia: return "en_LR"
+ case .Macao: return "zh_MO"
+ case .Malaysia: return "ms_MY"
+ case .Malta: return "mt_MT"
+ case .Mongolia: return "mn_MN"
+ case .Morocco: return "ar_MA"
+ case .Myanmar: return "my_MM"
+ case .Nicaragua: return "es_NI"
+ case .Pakistan: return "ur_PK"
+ case .Panama: return "es_PA"
+ case .Russia: return "ru_RU"
+ case .Senegal: return "fr_SN"
+ case .DemocraticRepCongo: return "fr_CD"
+ case .Uganda: return "en_UG"
+ case .Ukraine: return "uk_UA"
+ case .Venezuela: return "es_VE"
+ case .Yemen: return "ar_YE"
+ case .Zimbabwe: return "en_ZW"
+ }
+ }
+}
diff --git a/litewallet/NoBuyTabBarViewController.swift b/litewallet/NoBuyTabBarViewController.swift
new file mode 100644
index 000000000..b78189ac2
--- /dev/null
+++ b/litewallet/NoBuyTabBarViewController.swift
@@ -0,0 +1,419 @@
+import Foundation
+import UIKit
+
+class NoBuyTabBarViewController: UIViewController, Subscriber, Trackable, UITabBarDelegate {
+ let kInitialChildViewControllerIndex = 0 // TransactionsViewController
+ @IBOutlet var headerView: UIView!
+ @IBOutlet var containerView: UIView!
+ @IBOutlet var tabBar: UITabBar!
+ @IBOutlet var settingsButton: UIButton!
+ @IBOutlet var walletBalanceLabel: UILabel!
+
+ var primaryBalanceLabel: UpdatingLabel?
+ var secondaryBalanceLabel: UpdatingLabel?
+ private let largeFontSize: CGFloat = 24.0
+ private let smallFontSize: CGFloat = 12.0
+ private var hasInitialized = false
+ private let dateFormatter = DateFormatter()
+ private let equalsLabel = UILabel(font: .barlowMedium(size: 12), color: .whiteTint)
+ private var regularConstraints: [NSLayoutConstraint] = []
+ private var swappedConstraints: [NSLayoutConstraint] = []
+ private let currencyTapView = UIView()
+ private let storyboardNames: [String] = ["Transactions", "Send", "Receive"]
+ var storyboardIDs: [String] = ["TransactionsViewController", "SendLTCViewController", "ReceiveLTCViewController"]
+ var viewControllers: [UIViewController] = []
+ var activeController: UIViewController?
+ var updateTimer: Timer?
+ var store: Store?
+ var walletManager: WalletManager?
+ var userIsMoonPaySupported: Bool?
+ var exchangeRate: Rate? {
+ didSet { setBalances() }
+ }
+
+ private var balance: UInt64 = 0 {
+ didSet { setBalances() }
+ }
+
+ var isLtcSwapped: Bool? {
+ didSet { setBalances() }
+ }
+
+ @IBAction func showSettingsAction(_: Any) {
+ guard let store = store
+ else {
+ NSLog("ERROR: Store not set")
+ return
+ }
+ store.perform(action: RootModalActions.Present(modal: .menu))
+ }
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ setupModels()
+ setupViews()
+ configurePriceLabels()
+ addSubscriptions()
+ dateFormatter.setLocalizedDateFormatFromTemplate("MMM d, h:mm a")
+
+ addViewControllers()
+
+ updateTimer = Timer.scheduledTimer(withTimeInterval: 30.0, repeats: true) { _ in
+ self.setBalances()
+ }
+
+ guard let array = tabBar.items
+ else {
+ NSLog("ERROR: no items found")
+ return
+ }
+ tabBar.selectedItem = array[kInitialChildViewControllerIndex]
+
+ NotificationCenter.default.addObserver(self, selector: #selector(languageChanged), name: .languageChangedNotification, object: nil)
+ }
+
+ deinit {
+ NotificationCenter.default.removeObserver(self, name: .languageChangedNotification, object: nil)
+ self.updateTimer = nil
+ }
+
+ @objc
+ func languageChanged() {
+ walletBalanceLabel.text = S.ManageWallet.balance.localize() + ":"
+ localizeTabBar()
+ viewControllers = []
+ addViewControllers()
+ guard let array = tabBar.items else { return }
+ tabBar.selectedItem = array[kInitialChildViewControllerIndex]
+ displayContentController(contentController: viewControllers[0])
+ }
+
+ func addViewControllers() {
+ for (index, storyboardID) in storyboardIDs.enumerated() {
+ if storyboardID == "BuyHostingController" && (userIsMoonPaySupported != nil) {
+ let hostingController = BuyHostingController()
+ viewControllers.append(hostingController)
+ } else {
+ let controller = UIStoryboard(name: storyboardNames[index], bundle: nil).instantiateViewController(withIdentifier: storyboardID)
+ viewControllers.append(controller)
+ }
+ }
+ }
+
+ private func setupModels() {
+ guard let store = store else { return }
+
+ isLtcSwapped = store.state.isLtcSwapped
+
+ if let rate = store.state.currentRate {
+ exchangeRate = rate
+ let placeholderAmount = Amount(amount: 0, rate: rate, maxDigits: store.state.maxDigits)
+ secondaryBalanceLabel = UpdatingLabel(formatter: placeholderAmount.localFormat)
+ primaryBalanceLabel = UpdatingLabel(formatter: placeholderAmount.ltcFormat)
+ } else {
+ secondaryBalanceLabel = UpdatingLabel(formatter: NumberFormatter())
+ primaryBalanceLabel = UpdatingLabel(formatter: NumberFormatter())
+ }
+ }
+
+ private func setupViews() {
+ walletBalanceLabel.text = S.ManageWallet.balance.localize() + ":"
+
+ headerView.backgroundColor = .liteWalletBlue
+ tabBar.barTintColor = .liteWalletBlue
+ containerView.backgroundColor = .liteWalletBlue
+ view.backgroundColor = .liteWalletBlue
+ }
+
+ private func configurePriceLabels() {
+ // TODO: Debug the reizing of label...very important
+ guard let primaryLabel = primaryBalanceLabel,
+ let secondaryLabel = secondaryBalanceLabel
+ else {
+ NSLog("ERROR: Price labels not initialized")
+ return
+ }
+
+ let priceLabelArray = [primaryBalanceLabel, secondaryBalanceLabel, equalsLabel]
+
+ for (_, view) in priceLabelArray.enumerated() {
+ view?.backgroundColor = .clear
+ view?.textColor = .white
+ }
+
+ primaryLabel.font = UIFont.barlowSemiBold(size: largeFontSize)
+ secondaryLabel.font = UIFont.barlowSemiBold(size: largeFontSize)
+
+ equalsLabel.text = "="
+ headerView.addSubview(primaryLabel)
+ headerView.addSubview(secondaryLabel)
+ headerView.addSubview(equalsLabel)
+ headerView.addSubview(currencyTapView)
+
+ secondaryLabel.constrain([
+ secondaryLabel.constraint(.firstBaseline, toView: primaryLabel, constant: 0.0),
+ ])
+
+ equalsLabel.translatesAutoresizingMaskIntoConstraints = false
+ primaryLabel.translatesAutoresizingMaskIntoConstraints = false
+ regularConstraints = [
+ primaryLabel.firstBaselineAnchor.constraint(equalTo: headerView.bottomAnchor, constant: -12),
+ primaryLabel.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: C.padding[1] * 1.25),
+ equalsLabel.firstBaselineAnchor.constraint(equalTo: primaryLabel.firstBaselineAnchor, constant: 0),
+ equalsLabel.leadingAnchor.constraint(equalTo: primaryLabel.trailingAnchor, constant: C.padding[1] / 2.0),
+ secondaryLabel.leadingAnchor.constraint(equalTo: equalsLabel.trailingAnchor, constant: C.padding[1] / 2.0),
+ ]
+
+ swappedConstraints = [
+ secondaryLabel.firstBaselineAnchor.constraint(equalTo: headerView.bottomAnchor, constant: -12),
+ secondaryLabel.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: C.padding[1] * 1.25),
+ equalsLabel.firstBaselineAnchor.constraint(equalTo: secondaryLabel.firstBaselineAnchor, constant: 0),
+ equalsLabel.leadingAnchor.constraint(equalTo: secondaryLabel.trailingAnchor, constant: C.padding[1] / 2.0),
+ primaryLabel.leadingAnchor.constraint(equalTo: equalsLabel.trailingAnchor, constant: C.padding[1] / 2.0),
+ ]
+
+ if let isLTCSwapped = isLtcSwapped {
+ NSLayoutConstraint.activate(isLTCSwapped ? swappedConstraints : regularConstraints)
+ }
+
+ currencyTapView.constrain([
+ currencyTapView.leadingAnchor.constraint(equalTo: headerView.leadingAnchor, constant: 0),
+ currencyTapView.trailingAnchor.constraint(equalTo: settingsButton.leadingAnchor, constant: -C.padding[5]),
+ currencyTapView.topAnchor.constraint(equalTo: primaryLabel.topAnchor, constant: 0),
+ currencyTapView.bottomAnchor.constraint(equalTo: primaryLabel.bottomAnchor, constant: C.padding[1]),
+ ])
+
+ let gr = UITapGestureRecognizer(target: self, action: #selector(currencySwitchTapped))
+ currencyTapView.addGestureRecognizer(gr)
+ }
+
+ // MARK: - Adding Subscriptions
+
+ private func addSubscriptions() {
+ guard let store = store
+ else {
+ NSLog("ERROR - Store not passed")
+ return
+ }
+
+ guard let primaryLabel = primaryBalanceLabel,
+ let secondaryLabel = secondaryBalanceLabel
+ else {
+ NSLog("ERROR: Price labels not initialized")
+ return
+ }
+
+ store.subscribe(self, selector: { $0.walletState.syncProgress != $1.walletState.syncProgress },
+ callback: { _ in
+ self.tabBar.selectedItem = self.tabBar.items?.first
+ })
+
+ store.lazySubscribe(self,
+ selector: { $0.isLtcSwapped != $1.isLtcSwapped },
+ callback: { self.isLtcSwapped = $0.isLtcSwapped })
+ store.lazySubscribe(self,
+ selector: { $0.currentRate != $1.currentRate },
+ callback: {
+ if let rate = $0.currentRate {
+ let placeholderAmount = Amount(amount: 0, rate: rate, maxDigits: $0.maxDigits)
+ secondaryLabel.formatter = placeholderAmount.localFormat
+ primaryLabel.formatter = placeholderAmount.ltcFormat
+ }
+ self.exchangeRate = $0.currentRate
+ })
+
+ store.lazySubscribe(self,
+ selector: { $0.maxDigits != $1.maxDigits },
+ callback: {
+ if let rate = $0.currentRate {
+ let placeholderAmount = Amount(amount: 0, rate: rate, maxDigits: $0.maxDigits)
+ secondaryLabel.formatter = placeholderAmount.localFormat
+ primaryLabel.formatter = placeholderAmount.ltcFormat
+ self.setBalances()
+ }
+ })
+
+ store.subscribe(self,
+ selector: { $0.walletState.balance != $1.walletState.balance },
+ callback: { state in
+ if let balance = state.walletState.balance {
+ self.balance = balance
+ self.setBalances()
+ }
+ })
+ }
+
+ /// This is called when the price changes
+ private func setBalances() {
+ guard let rate = exchangeRate, let store = store, let isLTCSwapped = isLtcSwapped
+ else {
+ NSLog("ERROR: Rate, Store not initialized")
+ return
+ }
+ guard let primaryLabel = primaryBalanceLabel,
+ let secondaryLabel = secondaryBalanceLabel
+ else {
+ NSLog("ERROR: Price labels not initialized")
+ return
+ }
+
+ let amount = Amount(amount: balance, rate: rate, maxDigits: store.state.maxDigits)
+
+ if !hasInitialized {
+ let amount = Amount(amount: balance, rate: exchangeRate!, maxDigits: store.state.maxDigits)
+ NSLayoutConstraint.deactivate(isLTCSwapped ? regularConstraints : swappedConstraints)
+ NSLayoutConstraint.activate(isLTCSwapped ? swappedConstraints : regularConstraints)
+ primaryLabel.setValue(amount.amountForLtcFormat)
+ secondaryLabel.setValue(amount.localAmount)
+ if isLTCSwapped {
+ primaryLabel.transform = transform(forView: primaryLabel)
+ } else {
+ secondaryLabel.transform = transform(forView: secondaryLabel)
+ }
+ hasInitialized = true
+ } else {
+ if primaryLabel.isHidden {
+ primaryLabel.isHidden = false
+ }
+
+ if secondaryLabel.isHidden {
+ secondaryLabel.isHidden = false
+ }
+ }
+
+ primaryLabel.setValue(amount.amountForLtcFormat)
+ secondaryLabel.setValue(amount.localAmount)
+
+ if !isLTCSwapped {
+ primaryLabel.transform = .identity
+ secondaryLabel.transform = transform(forView: secondaryLabel)
+ } else {
+ secondaryLabel.transform = .identity
+ primaryLabel.transform = transform(forView: primaryLabel)
+ }
+ }
+
+ /// Transform LTC and Fiat Balances
+ /// - Parameter forView: Views
+ /// - Returns: the inverse transform
+ private func transform(forView: UIView) -> CGAffineTransform {
+ forView.transform = .identity
+ let scaleFactor: CGFloat = smallFontSize / largeFontSize
+ let deltaX = forView.frame.width * (1 - scaleFactor)
+ let deltaY = forView.frame.height * (1 - scaleFactor)
+ let scale = CGAffineTransform(scaleX: scaleFactor, y: scaleFactor)
+ return scale.translatedBy(x: -deltaX, y: deltaY / 2.0)
+ }
+
+ override func viewWillAppear(_ animated: Bool) {
+ super.viewWillAppear(animated)
+ localizeTabBar()
+ }
+
+ func localizeTabBar() {
+ guard let array = tabBar.items
+ else {
+ NSLog("ERROR: no items found")
+ return
+ }
+
+ for item in array {
+ switch item.tag {
+ case 0: item.title = S.History.barItemTitle.localize()
+ case 1: item.title = S.Send.barItemTitle.localize()
+ case 2: item.title = S.Receive.barItemTitle.localize()
+ default:
+ item.title = "NO-TITLE"
+ NSLog("ERROR: UITabbar item count is wrong")
+ }
+ }
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+ displayContentController(contentController: viewControllers[kInitialChildViewControllerIndex])
+ }
+
+ func displayContentController(contentController: UIViewController) {
+ // MARK: - Tab View Controllers Configuration
+
+ switch NSStringFromClass(contentController.classForCoder) {
+ case "litewallet.TransactionsViewController":
+
+ guard let transactionVC = contentController as? TransactionsViewController
+ else {
+ return
+ }
+
+ transactionVC.store = store
+ transactionVC.walletManager = walletManager
+ transactionVC.isLtcSwapped = store?.state.isLtcSwapped
+
+ case "litewallet.SendLTCViewController":
+ guard let sendVC = contentController as? SendLTCViewController
+ else {
+ return
+ }
+
+ sendVC.store = store
+
+ case "litewallet.ReceiveLTCViewController":
+ guard let receiveVC = contentController as? ReceiveLTCViewController
+ else {
+ return
+ }
+ receiveVC.store = store
+
+ default:
+ fatalError("Tab viewController not set")
+ }
+ exchangeRate = TransactionManager.sharedInstance.rate
+
+ addChild(contentController)
+ contentController.view.frame = containerView.frame
+ view.addSubview(contentController.view)
+ contentController.didMove(toParent: self)
+ activeController = contentController
+ }
+
+ func hideContentController(contentController: UIViewController) {
+ contentController.willMove(toParent: nil)
+ contentController.view.removeFromSuperview()
+ contentController.removeFromParent()
+ }
+
+ func tabBar(_: UITabBar, didSelect item: UITabBarItem) {
+ if let tempActiveController = activeController {
+ hideContentController(contentController: tempActiveController)
+ }
+
+ // DEV: This happens because it relies on the tab in the storyboard tag
+ displayContentController(contentController: viewControllers[item.tag])
+ }
+}
+
+extension NoBuyTabBarViewController {
+ @objc private func currencySwitchTapped() {
+ view.layoutIfNeeded()
+ guard let store = store else { return }
+ guard let isLTCSwapped = isLtcSwapped else { return }
+ guard let primaryLabel = primaryBalanceLabel,
+ let secondaryLabel = secondaryBalanceLabel
+ else {
+ NSLog("ERROR: Price labels not initialized")
+ return
+ }
+
+ UIView.spring(0.7, animations: {
+ primaryLabel.transform = primaryLabel.transform.isIdentity ? self.transform(forView: primaryLabel) : .identity
+ secondaryLabel.transform = secondaryLabel.transform.isIdentity ? self.transform(forView: secondaryLabel) : .identity
+ NSLayoutConstraint.deactivate(!isLTCSwapped ? self.regularConstraints : self.swappedConstraints)
+ NSLayoutConstraint.activate(!isLTCSwapped ? self.swappedConstraints : self.regularConstraints)
+ self.view.layoutIfNeeded()
+
+ LWAnalytics.logEventWithParameters(itemName: ._20200207_DTHB)
+
+ }) { _ in }
+ store.perform(action: CurrencyChange.toggle())
+ }
+}
diff --git a/litewallet/Platform/TxMetaData.swift b/litewallet/Platform/TxMetaData.swift
index 013289982..45bf54b4e 100644
--- a/litewallet/Platform/TxMetaData.swift
+++ b/litewallet/Platform/TxMetaData.swift
@@ -52,7 +52,7 @@ open class TxMetaData: BRKVStoreObject, BRCoding {
var del: Bool
var bytes: [UInt8]
- print("[BRTxMetadataObject] find \(txHash.txKey)")
+ print("[BRTxMetadataObject] find txHash \(txHash.txKey)")
do {
(ver, date, del, bytes) = try store.get(txHash.txKey)
let bytesDat = Data(bytes: &bytes, count: bytes.count)
@@ -72,7 +72,7 @@ open class TxMetaData: BRKVStoreObject, BRCoding {
var del: Bool
var bytes: [UInt8]
- print("[BRTxMetadataObject] find \(txKey)")
+ print("[BRTxMetadataObject] find txKey \(txKey)")
do {
(ver, date, del, bytes) = try store.get(txKey)
let bytesDat = Data(bytes: &bytes, count: bytes.count)
diff --git a/litewallet/Storyboards/Buy.storyboard b/litewallet/Storyboards/Buy.storyboard
index 874415f3a..d4ec41840 100644
--- a/litewallet/Storyboards/Buy.storyboard
+++ b/litewallet/Storyboards/Buy.storyboard
@@ -9,9 +9,6 @@
-
- BarlowSemiCondensed-Bold
-
BarlowSemiCondensed-Light
@@ -20,247 +17,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -370,10 +126,7 @@
-
-
-
diff --git a/litewallet/Storyboards/Main.storyboard b/litewallet/Storyboards/Main.storyboard
index c648ac707..080ef3a9d 100644
--- a/litewallet/Storyboards/Main.storyboard
+++ b/litewallet/Storyboards/Main.storyboard
@@ -1,9 +1,9 @@
-
+
-
+
@@ -32,7 +32,8 @@
-
+
+
@@ -118,7 +119,6 @@
-
@@ -127,7 +127,7 @@
-
+
@@ -137,6 +137,95 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -145,7 +234,7 @@
-
+
diff --git a/litewallet/Strings/Base.lproj/Localizable.strings b/litewallet/Strings/Base.lproj/Localizable.strings
index d07f2e339..385d568fb 100644
--- a/litewallet/Strings/Base.lproj/Localizable.strings
+++ b/litewallet/Strings/Base.lproj/Localizable.strings
@@ -1069,9 +1069,6 @@
/* $53.09/L + 1.07% */
"Confirmation.amountDetailLabel" = "Exchange details:";
-/* Short Network Fee: ($1.00) */
-"Confirmation.shortFeeLabel" = "FEE:";
-
/* Address label */
"Confirmation.staticAddressLabel" = "ADDRESS:";
@@ -1429,18 +1426,6 @@
/* sorry */
"Fragment.sorry" = "sorry";
-/* 2FA Error message */
-"LitecoinCard.twoFAErrorMessage" = "There was an error. Please toggle 2FA to *Enabled*, enter the emailed code, and try again.";
-
-/* Enter domain */
-"Send.UnstoppableDomains.simpleplaceholder" = "Enter domain";
-
-/* Enter a */
-"Send.UnstoppableDomains.enterA" = "Enter a";
-
-/* domain */
-"Send.UnstoppableDomains.domain" = "domain";
-
/* Change language alert message */
"Settings.ChangeLanguage.alertMessage" = "Are you sure you want to change the language to %l?";
diff --git a/litewallet/Strings/it.lproj/Localizable.strings b/litewallet/Strings/it.lproj/Localizable.strings
index 699d1997a..985939b1a 100755
--- a/litewallet/Strings/it.lproj/Localizable.strings
+++ b/litewallet/Strings/it.lproj/Localizable.strings
@@ -718,12 +718,6 @@
/* Fees: $0.01*/
"Send.fee" = "Commissioni: %1$@";
-/* Fees: $0.01*/
-"Send.fee" = "Commissioni: %1$@";
-
-/* Fees Blank: */
-"Send.feeBlank" = "Commissioni:";
-
/* Fees Blank: */
"Send.feeBlank" = "Commissioni:";
diff --git a/litewallet/SupportLitecoinFoundationView.swift b/litewallet/SupportLitecoinFoundationView.swift
index fd2bce07e..1b7acb452 100644
--- a/litewallet/SupportLitecoinFoundationView.swift
+++ b/litewallet/SupportLitecoinFoundationView.swift
@@ -9,9 +9,6 @@ struct SupportLitecoinFoundationView: View {
@ObservedObject
var viewModel: SupportLitecoinFoundationViewModel
- @State
- private var showSupportLFPage: Bool = false
-
// MARK: - Public
var supportSafariView = SupportSafariView(url: FoundationSupport.url,
diff --git a/litewallet/TabBarViewController.swift b/litewallet/TabBarViewController.swift
index f80e4370a..8af223d8a 100644
--- a/litewallet/TabBarViewController.swift
+++ b/litewallet/TabBarViewController.swift
@@ -20,12 +20,13 @@ class TabBarViewController: UIViewController, Subscriber, Trackable, UITabBarDel
private var swappedConstraints: [NSLayoutConstraint] = []
private let currencyTapView = UIView()
private let storyboardNames: [String] = ["Transactions", "Send", "Receive", "Buy"]
- var storyboardIDs: [String] = ["TransactionsViewController", "SendLTCViewController", "ReceiveLTCViewController", "BuyTableViewController"]
+ var storyboardIDs: [String] = ["TransactionsViewController", "SendLTCViewController", "ReceiveLTCViewController", "BuyHostingController"]
var viewControllers: [UIViewController] = []
var activeController: UIViewController?
var updateTimer: Timer?
var store: Store?
var walletManager: WalletManager?
+ var userIsMoonPaySupported: Bool?
var exchangeRate: Rate? {
didSet { setBalances() }
}
@@ -89,8 +90,13 @@ class TabBarViewController: UIViewController, Subscriber, Trackable, UITabBarDel
func addViewControllers() {
for (index, storyboardID) in storyboardIDs.enumerated() {
- let controller = UIStoryboard(name: storyboardNames[index], bundle: nil).instantiateViewController(withIdentifier: storyboardID)
- viewControllers.append(controller)
+ if storyboardID == "BuyHostingController" {
+ let hostingController = BuyHostingController()
+ viewControllers.append(hostingController)
+ } else {
+ let controller = UIStoryboard(name: storyboardNames[index], bundle: nil).instantiateViewController(withIdentifier: storyboardID)
+ viewControllers.append(controller)
+ }
}
}
@@ -344,13 +350,13 @@ class TabBarViewController: UIViewController, Subscriber, Trackable, UITabBarDel
transactionVC.walletManager = walletManager
transactionVC.isLtcSwapped = store?.state.isLtcSwapped
- case "litewallet.BuyTableViewController":
- guard let buyVC = contentController as? BuyTableViewController
+ case "litewallet.BuyHostingController":
+ guard let buyHC = contentController as? BuyHostingController
else {
return
}
- buyVC.store = store
- buyVC.walletManager = walletManager
+
+ buyHC.isLoaded = true
case "litewallet.SendLTCViewController":
guard let sendVC = contentController as? SendLTCViewController
diff --git a/litewallet/TransactionsViewModel.swift b/litewallet/TransactionsViewModel.swift
deleted file mode 100644
index 300ee9af6..000000000
--- a/litewallet/TransactionsViewModel.swift
+++ /dev/null
@@ -1,15 +0,0 @@
-import Foundation
-
-class TransactionsViewModel: ObservableObject {
- var store: Store
-
- var walletManager: WalletManager
-
- var isLTCSwapped: Bool = false
-
- init(store: Store, walletManager: WalletManager) {
- self.store = store
- self.walletManager = walletManager
- isLTCSwapped = store.state.isLtcSwapped
- }
-}
diff --git a/litewallet/TransferAmountViewModel.swift b/litewallet/TransferAmountViewModel.swift
index 3519d6456..8b1378917 100644
--- a/litewallet/TransferAmountViewModel.swift
+++ b/litewallet/TransferAmountViewModel.swift
@@ -1,73 +1 @@
-import BRCore
-import Foundation
-import KeychainAccess
-import UIKit
-// DEV: To be removed in following issue https://github.com/litecoin-foundation/litewallet-ios/issues/177
-
-class TransferAmountViewModel: ObservableObject {
- // MARK: - Combine Variables
-
- @Published
- var walletType: WalletType
-
- // MARK: - Private Variables
-
- private let walletManager: WalletManager
-
- private let store: Store
-
- private var sender: Sender?
-
- // MARK: - Public Variables
-
- var litewalletBalance: Double = 0.0
-
- var litewalletAddress: String = ""
-
- var cardBalance: Double = 0.0
-
- var cardAddress: String = ""
-
- var currentBalance: Double = 0.0
-
- var transferAmount: Double = 0.0
-
- /// This is the LTC address the wallet is sending LTC TO
- var destinationAddress: String {
- return walletType == .litewallet ? cardAddress : litewalletAddress
- }
-
- var transaction: BRTxRef?
-
- init(walletType: WalletType,
- litewalletBalance: Double,
- litewalletAddress: String,
- cardBalance: Double,
- cardAddress: String,
- walletManager: WalletManager,
- store: Store)
- {
- self.walletManager = walletManager
-
- self.store = store
-
- self.walletType = walletType
-
- self.litewalletBalance = litewalletBalance
-
- self.litewalletAddress = litewalletAddress
-
- // DEV: The Testnet is not implemented in Loafwallet Core.
- // This would be used for the Card testing.
- #if DEBUG
- self.litewalletAddress = MockData.testLTCAddress
- #endif
-
- self.cardBalance = cardBalance
-
- self.cardAddress = cardAddress
-
- currentBalance = walletType == .litewallet ? litewalletBalance : cardBalance
- }
-}
diff --git a/litewallet/Views/AlertView.swift b/litewallet/Views/AlertView.swift
index 58a72e7db..a4df9dcbd 100644
--- a/litewallet/Views/AlertView.swift
+++ b/litewallet/Views/AlertView.swift
@@ -4,7 +4,6 @@ enum AlertType {
case pinSet(callback: () -> Void)
case paperKeySet(callback: () -> Void)
case sendSuccess
- case resolvedSuccess
case addressesCopied
case sweepSuccess(callback: () -> Void)
@@ -19,8 +18,6 @@ enum AlertType {
return S.SecurityAlerts.paperKeySet.localize()
case .sendSuccess:
return S.SecurityAlerts.sendSuccess.localize()
- case .resolvedSuccess:
- return S.SecurityAlerts.resolvedSuccess.localize()
case .addressesCopied:
return S.SecurityAlerts.copiedAddressesHeader.localize()
case .sweepSuccess:
@@ -40,8 +37,6 @@ enum AlertType {
return S.SecurityAlerts.paperKeySetSubheader.localize()
case .sendSuccess:
return S.SecurityAlerts.sendSuccessSubheader.localize()
- case .resolvedSuccess:
- return S.SecurityAlerts.resolvedSuccessSubheader.localize()
case .addressesCopied:
return S.SecurityAlerts.copiedAddressesSubheader.localize()
case .sweepSuccess:
@@ -68,8 +63,6 @@ func == (lhs: AlertType, rhs: AlertType) -> Bool {
return true
case (.sendSuccess, .sendSuccess):
return true
- case (.resolvedSuccess, .resolvedSuccess):
- return true
case (.addressesCopied, .addressesCopied):
return true
case (.sweepSuccess(_), .sweepSuccess(_)):
diff --git a/litewallet/Wallet/ExchangeUpdater.swift b/litewallet/Wallet/ExchangeUpdater.swift
index 5b52eb0a0..f4f18422f 100644
--- a/litewallet/Wallet/ExchangeUpdater.swift
+++ b/litewallet/Wallet/ExchangeUpdater.swift
@@ -15,11 +15,13 @@ class ExchangeUpdater: Subscriber {
}
func refresh(completion: @escaping () -> Void) {
- walletManager.apiClient?.exchangeRates { rates, _ in
+ if walletManager.store.state.walletState.syncState != .syncing {
+ walletManager.apiClient?.exchangeRates { rates, _ in
- guard let currentRate = rates.first(where: { $0.code == self.store.state.defaultCurrencyCode }) else { completion(); return }
- self.store.perform(action: ExchangeRates.setRates(currentRate: currentRate, rates: rates))
- completion()
+ guard let currentRate = rates.first(where: { $0.code == self.store.state.defaultCurrencyCode }) else { completion(); return }
+ self.store.perform(action: ExchangeRates.setRates(currentRate: currentRate, rates: rates))
+ completion()
+ }
}
}
diff --git a/litewallet/WalletCoordinator.swift b/litewallet/WalletCoordinator.swift
index 784c24f27..dc1ab8925 100644
--- a/litewallet/WalletCoordinator.swift
+++ b/litewallet/WalletCoordinator.swift
@@ -3,8 +3,8 @@ import Foundation
import UIKit
private let lastBlockHeightKey = "LastBlockHeightKey"
-private let progressUpdateInterval: TimeInterval = 1.0
-private let updateDebounceInterval: TimeInterval = 1.0
+private let progressUpdateInterval: TimeInterval = 0.5
+private let updateDebounceInterval: TimeInterval = 0.4
class WalletCoordinator: Subscriber, Trackable {
var kvStore: BRReplicatedKVStore? {
diff --git a/litewallet/bitrefill_index.html b/litewallet/bitrefill_index.html
deleted file mode 100644
index f60fdc9cd..000000000
--- a/litewallet/bitrefill_index.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
- Bitrefill
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/litewallet/de.lproj/Localizable.strings b/litewallet/de.lproj/Localizable.strings
index b5ba77126..b22946220 100755
--- a/litewallet/de.lproj/Localizable.strings
+++ b/litewallet/de.lproj/Localizable.strings
@@ -904,21 +904,6 @@
/* Fees: $0.01*/
"Send.fee" = "Gebühren: %1$@";
-/* Fees: $0.01*/
-"Send.fee" = "Gebühren: %1$@";
-
-/* Fees: $0.01*/
-"Send.fee" = "Gebühren: %1$@";
-
-/* Fees Blank: */
-"Send.feeBlank" = "Gebühren:";
-
-/* Fees Blank: */
-"Send.feeBlank" = "Gebühren:";
-
-/* Fees Blank: */
-"Send.feeBlank" = "Gebühren:";
-
/* Fees Blank: */
"Send.feeBlank" = "Gebühren:";
diff --git a/litewallet/en.lproj/Localizable.strings b/litewallet/en.lproj/Localizable.strings
index 4cc13379c..d93df6696 100644
--- a/litewallet/en.lproj/Localizable.strings
+++ b/litewallet/en.lproj/Localizable.strings
@@ -907,18 +907,6 @@
/* Fees: $0.01*/
"Send.fee" = "Fees: %1$@";
-/* Fees: $0.01*/
-"Send.fee" = "Fees: %1$@";
-
-/* Fees: $0.01*/
-"Send.fee" = "Fees: %1$@";
-
-/* Fees Blank: */
-"Send.feeBlank" = "Fees:";
-
-/* Fees Blank: */
-"Send.feeBlank" = "Fees:";
-
/* Fees Blank: */
"Send.feeBlank" = "Fees:";
diff --git a/litewallet/general.css b/litewallet/general.css
deleted file mode 100644
index c1652674a..000000000
--- a/litewallet/general.css
+++ /dev/null
@@ -1,55 +0,0 @@
-/* http://meyerweb.com/eric/tools/css/reset/
- v2.0 | 20110126
- License: none (public domain)
- */
-
-html, body, div, span, applet, object, iframe,
-h1, h2, h3, h4, h5, h6, p, blockquote, pre,
-a, abbr, acronym, address, big, cite, code,
-del, dfn, em, img, ins, kbd, q, s, samp,
-small, strike, strong, sub, sup, tt, var,
-b, u, i, center,
-dl, dt, dd, ol, ul, li,
-fieldset, form, label, legend,
-table, caption, tbody, tfoot, thead, tr, th, td,
-article, aside, canvas, details, embed,
-figure, figcaption, footer, header, hgroup,
-menu, nav, output, ruby, section, summary,
-time, mark, audio, video {
- margin: 0;
- padding: 0;
- border: 0;
- font-size: 100%;
- font: inherit;
- vertical-align: baseline;
-}
-/* HTML5 display-role reset for older browsers */
-article, aside, details, figcaption, figure,
-footer, header, hgroup, menu, nav, section {
- display: block;
-}
-body {
- line-height: 1;
-}
-ol, ul {
- list-style: none;
-}
-blockquote, q {
- quotes: none;
-}
-blockquote:before, blockquote:after,
-q:before, q:after {
- content: '';
- content: none;
-}
-table {
- border-collapse: collapse;
- border-spacing: 0;
-}
-
-* {
- -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
- -moz-box-sizing: border-box; /* Firefox, other Gecko */
- box-sizing: border-box; /* Opera/IE 8+ */
-}
-
diff --git a/litewalletTests/Class Tests/TabBarViewControllerTests.swift b/litewalletTests/Class Tests/TabBarViewControllerTests.swift
index d8a2fa4c8..053a9493e 100644
--- a/litewalletTests/Class Tests/TabBarViewControllerTests.swift
+++ b/litewalletTests/Class Tests/TabBarViewControllerTests.swift
@@ -4,6 +4,8 @@ import XCTest
class TabBarViewControllerTests: XCTestCase {
var viewController: TabBarViewController!
+ var noBuyVewController: NoBuyTabBarViewController!
+
override func setUpWithError() throws {
viewController = UIStoryboard(name: "Main",
bundle: nil)
@@ -11,16 +13,26 @@ class TabBarViewControllerTests: XCTestCase {
TabBarViewController
viewController.loadViewIfNeeded()
+
+ noBuyVewController = UIStoryboard(name: "Main",
+ bundle: nil)
+ .instantiateViewController(withIdentifier: "NoBuyTabBarViewController") as?
+ NoBuyTabBarViewController
+
+ noBuyVewController.loadViewIfNeeded()
}
override func tearDownWithError() throws {
viewController = nil
+ noBuyVewController = nil
}
func testTabBarItemCount() throws {
// There should be 4 tabs in this version for all users
XCTAssertTrue(viewController.tabBar.items?.count == 4)
+
+ XCTAssertTrue(noBuyVewController.tabBar.items?.count == 3)
}
func testTabBarItemRange() throws {
@@ -33,5 +45,11 @@ class TabBarViewControllerTests: XCTestCase {
XCTAssertTrue(viewController.tabBar.items?[2].tag == 2)
XCTAssertTrue(viewController.tabBar.items?[3].tag == 3)
+
+ XCTAssertTrue(noBuyVewController.tabBar.items?[0].tag == 0)
+
+ XCTAssertTrue(noBuyVewController.tabBar.items?[1].tag == 1)
+
+ XCTAssertTrue(noBuyVewController.tabBar.items?[2].tag == 2)
}
}
diff --git a/litewalletTests/Language Selection Tests/LocaleTests.swift b/litewalletTests/Language Selection Tests/LocaleTests.swift
new file mode 100644
index 000000000..efbfc489c
--- /dev/null
+++ b/litewalletTests/Language Selection Tests/LocaleTests.swift
@@ -0,0 +1,140 @@
+@testable import litewallet
+import XCTest
+
+final class LocaleTests: XCTestCase {
+ override func setUpWithError() throws {
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDownWithError() throws {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ }
+
+ func testFilteringUnsupportedCountries() throws {
+ /// Based on the live list: https://support.moonpay.com/customers/docs/moonpays_unsupported_countries
+
+ // Afghanistan: `fa_AF`, `ps_AF`, `uz_AF`
+ let afghanistanLocale = Locale(identifier: "fa_AF")
+ XCTAssertTrue(afghanistanLocale.identifier == "fa_AF")
+
+ // Barbados: `en_BB`
+ let barbadosLocale = Locale(identifier: "en_BB")
+ XCTAssertTrue(barbadosLocale.identifier == "en_BB")
+
+ // Belarus: `be_BY`, `ru_BY`
+ let belarusLocale = Locale(identifier: "be_BY")
+ XCTAssertTrue(belarusLocale.identifier == "be_BY")
+
+ // Burkina Faso: `fr_BF`
+ let burkinaFasoLocale = Locale(identifier: "fr_BF")
+ XCTAssertTrue(burkinaFasoLocale.identifier == "fr_BF")
+
+ // China: `zh_CN`, `zh_Hans_CN`, `zh_Hant_CN`, `ug_CN`
+ let chinaLocale = Locale(identifier: "zh_CN")
+ XCTAssertTrue(chinaLocale.identifier == "zh_CN")
+
+ // Iceland: `is_IS`
+ let icelandLocale = Locale(identifier: "is_IS")
+ XCTAssertTrue(icelandLocale.identifier == "is_IS")
+
+ // Iraq: `ar_IQ`, `ku_IQ`
+ let iraqLocale = Locale(identifier: "ar_IQ")
+ XCTAssertTrue(iraqLocale.identifier == "ar_IQ")
+
+ // Jamaica: `en_JM`, `jam_JM`
+ let jamaicaLocale = Locale(identifier: "en_JM")
+ XCTAssertTrue(jamaicaLocale.identifier == "en_JM")
+
+ // Japan: `ja_JP`
+ let japanLocale = Locale(identifier: "ja_JP")
+ XCTAssertTrue(japanLocale.identifier == "ja_JP")
+
+ // Kosovo: `sq_XK`, `sr_XK`
+ let kosovoLocale = Locale(identifier: "sq_XK")
+ XCTAssertTrue(kosovoLocale.identifier == "sq_XK")
+
+ // Liberia: `en_LR`
+ let liberiaLocale = Locale(identifier: "en_LR")
+ XCTAssertTrue(liberiaLocale.identifier == "en_LR")
+
+ // Macao: `zh_MO`, `pt_MO`
+ let macaoLocale = Locale(identifier: "zh_MO")
+ XCTAssertTrue(macaoLocale.identifier == "zh_MO")
+
+ // Malaysia: `ms_MY`, `zh_MY`, `ta_MY`, `en_MY`
+ let malaysiaLocale = Locale(identifier: "ms_MY")
+ XCTAssertTrue(malaysiaLocale.identifier == "ms_MY")
+
+ // Malta: `mt_MT`, `en_MT`
+ let maltaLocale = Locale(identifier: "mt_MT")
+ XCTAssertTrue(maltaLocale.identifier == "mt_MT")
+
+ // Mongolia: `mn_MN`
+ let mongoliaLocale = Locale(identifier: "mn_MN")
+ XCTAssertTrue(mongoliaLocale.identifier == "mn_MN")
+
+ // Morocco: `ar_MA`, `fr_MA`, `ber_MA`
+ let moroccoLocale = Locale(identifier: "ar_MA")
+ XCTAssertTrue(moroccoLocale.identifier == "ar_MA")
+
+ // Myanmar: `my_MM`
+ let myanmarLocale = Locale(identifier: "my_MM")
+ XCTAssertTrue(myanmarLocale.identifier == "my_MM")
+
+ // Nicaragua: `es_NI`
+ let nicaraguaLocale = Locale(identifier: "es_NI")
+ XCTAssertTrue(nicaraguaLocale.identifier == "es_NI")
+
+ // Pakistan: `ur_PK`, `en_PK`
+ let pakistanLocale = Locale(identifier: "ur_PK")
+ XCTAssertTrue(pakistanLocale.identifier == "ur_PK")
+
+ // Panama: `es_PA`
+ let panamaLocale = Locale(identifier: "es_PA")
+ XCTAssertTrue(panamaLocale.identifier == "es_PA")
+
+ // Russia: `ru_RU`
+ let russiaLocale = Locale(identifier: "ru_RU")
+ XCTAssertTrue(russiaLocale.identifier == "ru_RU")
+
+ // Senegal: `fr_SN`, `wo_SN`
+ let senegalLocale = Locale(identifier: "fr_SN")
+ XCTAssertTrue(senegalLocale.identifier == "fr_SN")
+
+ // The Democratic Republic Of The Congo: `fr_CD`, `ln_CD`, `sw_CD`
+ let drCongoLocale = Locale(identifier: "fr_CD")
+ XCTAssertTrue(drCongoLocale.identifier == "fr_CD")
+
+ // Uganda: `en_UG`, `sw_UG`
+ let ugandaLocale = Locale(identifier: "en_UG")
+ XCTAssertTrue(ugandaLocale.identifier == "en_UG")
+
+ // Ukraine: `uk_UA`, `ru_UA`
+ let ukraineLocale = Locale(identifier: "uk_UA")
+ XCTAssertTrue(ukraineLocale.identifier == "uk_UA")
+
+ // Venezuela: `es_VE`
+ let venezuelaLocale = Locale(identifier: "es_VE")
+ XCTAssertTrue(venezuelaLocale.identifier == "es_VE")
+
+ // Yemen: `ar_YE`
+ let yemenLocale = Locale(identifier: "ar_YE")
+ XCTAssertTrue(yemenLocale.identifier == "ar_YE")
+
+ // Zimbabwe: `en_ZW`, `sn_ZW`, `nd_ZW`
+ let zimbabweLocale = Locale(identifier: "en_ZW")
+ XCTAssertTrue(zimbabweLocale.identifier == "en_ZW")
+ }
+
+ func testUnsupportedCountriesEnum() throws {
+ let unsupportedCases = UnsupportedCountries.allCases
+ XCTAssertTrue(unsupportedCases.count == 28)
+
+ let supportedCountry = Locale(identifier: "en_US").identifier
+
+ for unsupportedLocale in unsupportedCases {
+ let unsupportedCode = unsupportedLocale.localeCode
+ XCTAssertTrue(unsupportedCode != supportedCountry)
+ }
+ }
+}