diff --git a/.fastlane/Fastfile b/.fastlane/Fastfile index d1e9a83..5425360 100644 --- a/.fastlane/Fastfile +++ b/.fastlane/Fastfile @@ -1,5 +1,5 @@ before_all do |lane| - carthage(platform: "all") + carthage end platform :ios do diff --git a/CHANGELOG.md b/CHANGELOG.md index bf14cbc..58fc84d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.2.0 +1. [[MNY-18](https://github.com/danthorpe/Money/pull/18)]: Adds Bitcoin currency types and support for % commission with FX. + * Creates `BTC` and `XBT` types. + * Refactors `FXQuote` into a struct (no longer subclass-able) but with a percentage commission property. Commission defaults to 0%. + * FX method `quote`, now returns `FXTransaction` as the value of the `Result`. This new value type composes the original base money, commission (in the same base money currency), the exchange rate, and the counter money. The type supports `ValueCoding`. + * A new FX provider, CEX.IO get support for buying and selling bitcoin using `USD`, `EUR` and `RUB`. + # 1.1.0 1. [[MNY-16](https://github.com/danthorpe/Money/pull/16)]: Grab bag of minor issues post 1.0 release. * Cleans up some minor mistakes (spelling etc). diff --git a/Examples/Custom Money/Custom Money/ViewController.swift b/Examples/Custom Money/Custom Money/ViewController.swift index 6ddaa89..4f4e784 100644 --- a/Examples/Custom Money/Custom Money/ViewController.swift +++ b/Examples/Custom Money/Custom Money/ViewController.swift @@ -19,7 +19,7 @@ class ViewController: UIViewController { print("You have \(hearts) and \(bees)") - let total = Bank.fx(hearts) + bees + let total = Bank.fx(hearts).counter + bees print("Exchanging your \(hearts) into \(Currency.Bee.symbol) via the bank gives you \(total) in total.") } diff --git a/Examples/Custom Money/Podfile.lock b/Examples/Custom Money/Podfile.lock index 668d1d4..abb3aae 100644 --- a/Examples/Custom Money/Podfile.lock +++ b/Examples/Custom Money/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - Money (1.0.0): + - Money (1.1.0): - Result (= 0.6.0-beta.6) - SwiftyJSON - ValueCoding @@ -15,7 +15,7 @@ EXTERNAL SOURCES: :path: "../../" SPEC CHECKSUMS: - Money: fdc3b1c89c626afe7ae0290742cd95d24bf6bb4b + Money: 9b12218fa90413e429f9f623f52619bb89791722 Result: dc390d0b58f9ec43fcd536f1ebdd130803cc6cbc SwiftyJSON: 592b53bee5ef3dd9b3bebc6b9cb7ee35426ae8c3 ValueCoding: 54486fde2d7b1c2f1eb46de260b95340abed5bde diff --git a/Examples/Custom Money/Pods/Local Podspecs/Money.podspec.json b/Examples/Custom Money/Pods/Local Podspecs/Money.podspec.json index 84469e6..339aa0e 100644 --- a/Examples/Custom Money/Pods/Local Podspecs/Money.podspec.json +++ b/Examples/Custom Money/Pods/Local Podspecs/Money.podspec.json @@ -1,6 +1,6 @@ { "name": "Money", - "version": "1.0.0", + "version": "1.1.0", "summary": "Swift types for working with Money.", "description": "Money is a Swift cross platform framework for iOS, watchOS, tvOS and OS X. \n\nIt provides types and functionality to help represent and manipulate money \nand currency related information.", "homepage": "https://github.com/danthorpe/Money", @@ -10,7 +10,7 @@ }, "source": { "git": "https://github.com/danthorpe/Money.git", - "tag": "1.0.0" + "tag": "1.1.0" }, "module_name": "Money", "social_media_url": "https://twitter.com/danthorpe", @@ -23,7 +23,8 @@ }, "source_files": [ "Money/*.swift", - "Money/Decimal/*.swift" + "Money/Decimal/*.swift", + "Money/FX/*.swift" ], "dependencies": { "ValueCoding": [ diff --git a/Examples/Custom Money/Pods/Manifest.lock b/Examples/Custom Money/Pods/Manifest.lock index 668d1d4..abb3aae 100644 --- a/Examples/Custom Money/Pods/Manifest.lock +++ b/Examples/Custom Money/Pods/Manifest.lock @@ -1,5 +1,5 @@ PODS: - - Money (1.0.0): + - Money (1.1.0): - Result (= 0.6.0-beta.6) - SwiftyJSON - ValueCoding @@ -15,7 +15,7 @@ EXTERNAL SOURCES: :path: "../../" SPEC CHECKSUMS: - Money: fdc3b1c89c626afe7ae0290742cd95d24bf6bb4b + Money: 9b12218fa90413e429f9f623f52619bb89791722 Result: dc390d0b58f9ec43fcd536f1ebdd130803cc6cbc SwiftyJSON: 592b53bee5ef3dd9b3bebc6b9cb7ee35426ae8c3 ValueCoding: 54486fde2d7b1c2f1eb46de260b95340abed5bde diff --git a/Examples/Custom Money/Pods/Pods.xcodeproj/project.pbxproj b/Examples/Custom Money/Pods/Pods.xcodeproj/project.pbxproj index 263f65c..67ac2f7 100644 --- a/Examples/Custom Money/Pods/Pods.xcodeproj/project.pbxproj +++ b/Examples/Custom Money/Pods/Pods.xcodeproj/project.pbxproj @@ -7,99 +7,102 @@ objects = { /* Begin PBXBuildFile section */ - 01F1F11219565EEDB994774F5458DBCC /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; + 0217EDAB41BE6D83A68B4A2339BBA762 /* Money-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 91C4C71A43800346A8BACEA8E5B05DA5 /* Money-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; 09F8C9409DF28C51561C0D4BCBDB7426 /* Pods-Custom Money-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D3CEE659D9C1D3DEA521E896D331964 /* Pods-Custom Money-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 205DE9495F6E98279A553429FDDF15B6 /* Money-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B01F2F57312E8852B8AAE2F384F620E /* Money-dummy.m */; }; - 30A618A1BC51A7D95D17A2067B21ACF0 /* ResultType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F003A917BF6D1C4FBA4D94B06C30179 /* ResultType.swift */; }; - 33F7DE75B0812B10F67D0420C6D71510 /* NSDecimalExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6A0B230AA93987BDA716F0FEBDCDA0E /* NSDecimalExtensions.swift */; }; + 16CC6804DA661658124C44577F2953E4 /* SwiftyJSON-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E2CDFCF407B3970A3F2FD3C19CCA4CE7 /* SwiftyJSON-dummy.m */; }; + 1F6A8EBF7DF1DD625F8CCDB7AED2F528 /* Currency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 196613FD4A9A760DD899B3999B10DE39 /* Currency.swift */; }; + 31E645E979F3A5B089FCD8DEC7A3536E /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1FC653D131B20022B75023F33F250B9 /* Result.framework */; }; 35575A63DB40EB8EC8BFD8189093A5DB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; - 3CD1D2DD10E273F86707E96E8BDB06AA /* ValueCoding-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B5E95FBF4C047EA6401BB7B12E42A8B7 /* ValueCoding-dummy.m */; }; - 3F1E9A6F32C74A0E158DF5FD355FDADD /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; - 40CD08E83AB8406EFF6DAD723DFA3AC3 /* ValueCoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5BC5B78EBB608AE95556AC64F2F724 /* ValueCoding.swift */; }; + 435ED888CA386BA222E288B1CC8574F5 /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB9149D7C1AAA968AE461BDB9D1EEE8 /* Result.swift */; }; 46B661B9D41457BFE21F2618E7CCC4E0 /* Pods-Custom Money-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9600516FB0E389F99DD6A409A89CA451 /* Pods-Custom Money-dummy.m */; }; - 563C2572D3B5DF7896E7626C05F0CE11 /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21ADF1E6DF190AAE9E0330490E4C3CF4 /* FX.swift */; }; - 5749D741D8442D600F69E17C2E0C571E /* DecimalNumberType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73CBCFF08B4E8BC27DCC0D5E90E976EA /* DecimalNumberType.swift */; }; - 591F03157805EB971E8A5D69F6F5112F /* Support.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED82986EB832C433BA892182F89597C6 /* Support.swift */; }; - 5E7CE62AF1775A4C8F8CE4336708FACF /* Result-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F158272DDE3E68231F6FE2A3DEB56C4E /* Result-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6E4DBC7F136D4F38ECD0AE3CB83A0676 /* Currency.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6C83A0ED4B948E127B8A02BBD7F0A9BA /* Currency.swift */; }; - 75DB6DD279AC32DEEE23F40E91029761 /* Money.swift in Sources */ = {isa = PBXBuildFile; fileRef = 03F95EC7386DACBA19CC5260381AADDE /* Money.swift */; }; - 78191570D151CEFFE5779A818A10D273 /* ValueCoding-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E593BAC0D422045A94607A9C0A277E /* ValueCoding-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 7A64F6E65EEA7AD7BA15349E04A6C17E /* Result-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D8F2976F6779F80CE007235A83876CE7 /* Result-dummy.m */; }; - 8E429C0288212DAB30AD1C19DD92D176 /* Result.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D1FC653D131B20022B75023F33F250B9 /* Result.framework */; }; - 9A09B11207C1722543A88B81FD18E43D /* SwiftyJSON-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E2CDFCF407B3970A3F2FD3C19CCA4CE7 /* SwiftyJSON-dummy.m */; }; - A5D79197F9C87AA12A55CF321D39FD9E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; - AB72AD9AEBAF9D656831C0593CB00F2C /* Money-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 91C4C71A43800346A8BACEA8E5B05DA5 /* Money-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - AE4219A42AA8CC10780AFC8B8603DEC7 /* ValueCoding.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C29D8E4CA9E4CF9452CBCB9F8D56071 /* ValueCoding.framework */; }; - B0590FC08FA8208B3D4A3F1C3B3D231F /* SwiftyJSON-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0216247E5703DEFCB395822BEDEDB978 /* SwiftyJSON-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B0BD516593207CE2DFF82F7428C2C0A9 /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31FCA3CC32B1FFB7E577A3FD7C8BDC8 /* SwiftyJSON.swift */; }; - D6564B72044D33B29B1ABCF62936AFF2 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77FD247247D6D3CDBF638A9DB0EBDB4E /* SwiftyJSON.framework */; }; - DF62EA9ACF4A13DAF30D77D29FF0A664 /* NSDecimalNumberExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3816C7DAA3910FD77039D0F101813083 /* NSDecimalNumberExtensions.swift */; }; - E8240E78A8B0F6B8EFD560880C1B7EA2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; - F099E4D77161FCDE09092A1EFE073689 /* Decimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = F3E2C607AAC7546F5DA1FF6E1D936464 /* Decimal.swift */; }; - FC421BD763CC47A66D9082814D727889 /* Autogenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFDAC51BCA9CA51E45E8E3EFF1115DC6 /* Autogenerated.swift */; }; - FCAC7A169DF92F4B209A2B4ADF0CEECC /* Result.swift in Sources */ = {isa = PBXBuildFile; fileRef = CCB9149D7C1AAA968AE461BDB9D1EEE8 /* Result.swift */; }; + 479158A06CDB3BB92C679F966E9D9E9E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; + 4C88E376338108DCA576487003CFC800 /* Yahoo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28A4E605F118FDFF037ACD0C2F7FA3CD /* Yahoo.swift */; }; + 4F31C9D988EDAA919718FC3BD4CDD785 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; + 4F45ED652CD2AAFDE8AEE11F158045B5 /* Money.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5EEF7A612BFA3D083C868A79762FB39 /* Money.swift */; }; + 554CF5A8F13DEE08C7DB61AF96C42E2A /* Result-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F158272DDE3E68231F6FE2A3DEB56C4E /* Result-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5637E947D3756585ECF976E01D38CC8A /* SwiftyJSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = C31FCA3CC32B1FFB7E577A3FD7C8BDC8 /* SwiftyJSON.swift */; }; + 685E5FA73478973B4D2184A91E4E7FF8 /* NSDecimalExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 597CFBA87C75BE144B401FCC1EC5C927 /* NSDecimalExtensions.swift */; }; + 7E586FC96883817FC458B25FA91BD2CE /* Bitcoin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 87218D77D4395E00D6D9170F8AFF291B /* Bitcoin.swift */; }; + 7FAE343617CB65AE9CB6BF5CFE4F1134 /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = EFF73AD3A7CF0FBE9BC94AEAC37858DD /* FX.swift */; }; + 80810DBE1DF76ECAAABA97CC92B7FC97 /* ValueCoding-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 65E593BAC0D422045A94607A9C0A277E /* ValueCoding-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 84964756F22AEE07130A328DC0143EFA /* ResultType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4F003A917BF6D1C4FBA4D94B06C30179 /* ResultType.swift */; }; + 84E7501479AACC41E67BB26817D9639D /* Autogenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8EEB490E417287676508AF49225E2B9 /* Autogenerated.swift */; }; + 8752AAACF89C0D05BAFAC976E18B43B5 /* OpenExchangeRates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 838F4AEA7BF1F57F0BE06B347D822D97 /* OpenExchangeRates.swift */; }; + 92290889D67198C19057765E18109214 /* ValueCoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED5BC5B78EBB608AE95556AC64F2F724 /* ValueCoding.swift */; }; + A235DAAECF32771AAA2A866446349A80 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; + ADF9BB52327C5FFC7A934CDA0EE843D9 /* ValueCoding-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = B5E95FBF4C047EA6401BB7B12E42A8B7 /* ValueCoding-dummy.m */; }; + B97D98FFAAA3C8A163AFDA70C5AAF75C /* SwiftyJSON-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 0216247E5703DEFCB395822BEDEDB978 /* SwiftyJSON-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + BFD28C75A55F161255F8F1C263D779F7 /* Money-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B01F2F57312E8852B8AAE2F384F620E /* Money-dummy.m */; }; + C664644B24E321B0A4A8568F929E69D8 /* ValueCoding.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C29D8E4CA9E4CF9452CBCB9F8D56071 /* ValueCoding.framework */; }; + CD10415D334D475BA55049F7F5027125 /* Support.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6555ECBB6D5CDDE1EA197618BD3509AD /* Support.swift */; }; + ECB837E114BC2BC4BBE280CE6CAE9BF4 /* NSDecimalNumberExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 212F2F7938CA183DECE52229884F8877 /* NSDecimalNumberExtensions.swift */; }; + EDA2FDCE4DBBD0C20B3C52525812F335 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 77FD247247D6D3CDBF638A9DB0EBDB4E /* SwiftyJSON.framework */; }; + F0A058EFFE6ECEE169C2B53704C78963 /* Decimal.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D811F4EED15D28415AF31F21F637295 /* Decimal.swift */; }; + F485847EBE24151C05EE62DCE7204EAF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */; }; + F796D5F5B55CE16B1311C41299E86D0B /* Result-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = D8F2976F6779F80CE007235A83876CE7 /* Result-dummy.m */; }; + F896F74FA7879D4F61DB699A27BF844D /* DecimalNumberType.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6E8271D7B956774CA6CD37674C3999C /* DecimalNumberType.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 1CA2F65C195043637C90F2888D138A77 /* PBXContainerItemProxy */ = { + 1DFE2A02B5C6BDFE88F8CA3DFB0FC286 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 3162227A40407035A6B7783E8DF419C0; - remoteInfo = Result; + remoteGlobalIDString = DCEA67B24DDEA58F2608D2A7E29EC0AE; + remoteInfo = Money; }; - 1DFE2A02B5C6BDFE88F8CA3DFB0FC286 /* PBXContainerItemProxy */ = { + 20E2555ABC7481F293A5C37138092ED3 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 7B7DCF1E0AA248CEB9ECEDA271F769CF; - remoteInfo = Money; + remoteGlobalIDString = 335D5C3164D7294DB478331EF58A0C4F; + remoteInfo = Result; }; 36023380F037B6AB8D4492DCA3A27CD5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 72F679D7EC35E44212F7DDF30676E432; + remoteGlobalIDString = E1BC6514E856EA889BE33605FA7C661A; remoteInfo = SwiftyJSON; }; - 41F272EA7F75CA2CEBC8E35579A501C9 /* PBXContainerItemProxy */ = { + 39651D11DAC97EA2B23D906D0DE433D1 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 3162227A40407035A6B7783E8DF419C0; - remoteInfo = Result; + remoteGlobalIDString = 5112C7EBB0119AC3BA1E726F52B37099; + remoteInfo = ValueCoding; }; - 7AA052775F912BADEC1FFCBF37B0CE8F /* PBXContainerItemProxy */ = { + 41F272EA7F75CA2CEBC8E35579A501C9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 72F679D7EC35E44212F7DDF30676E432; - remoteInfo = SwiftyJSON; + remoteGlobalIDString = 335D5C3164D7294DB478331EF58A0C4F; + remoteInfo = Result; }; - A8D7D5C5D4B2B0DBEA7CD9A1C6CA1131 /* PBXContainerItemProxy */ = { + 5C0A58B226E00A3E1A7328A37E81607F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 392A4CAB83070A6D2BFD53A02DBF3F3A; - remoteInfo = ValueCoding; + remoteGlobalIDString = E1BC6514E856EA889BE33605FA7C661A; + remoteInfo = SwiftyJSON; }; - FC9033D9680B4E91FEC3E2DAD8E754F3 /* PBXContainerItemProxy */ = { + A8D7D5C5D4B2B0DBEA7CD9A1C6CA1131 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = 392A4CAB83070A6D2BFD53A02DBF3F3A; + remoteGlobalIDString = 5112C7EBB0119AC3BA1E726F52B37099; remoteInfo = ValueCoding; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ 0216247E5703DEFCB395822BEDEDB978 /* SwiftyJSON-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftyJSON-umbrella.h"; sourceTree = ""; }; - 03F95EC7386DACBA19CC5260381AADDE /* Money.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Money.swift; sourceTree = ""; }; 0DA8BD07E1098E205AF45D501594137C /* Result.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = Result.modulemap; sourceTree = ""; }; + 196613FD4A9A760DD899B3999B10DE39 /* Currency.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = ""; }; 1DADDD5C59FCA27235ACA32605BD1527 /* SwiftyJSON-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "SwiftyJSON-prefix.pch"; sourceTree = ""; }; - 21ADF1E6DF190AAE9E0330490E4C3CF4 /* FX.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FX.swift; sourceTree = ""; }; + 212F2F7938CA183DECE52229884F8877 /* NSDecimalNumberExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NSDecimalNumberExtensions.swift; sourceTree = ""; }; 269178DAB03BE95581C9933E5AD7BA5E /* Result.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Result.xcconfig; sourceTree = ""; }; - 3816C7DAA3910FD77039D0F101813083 /* NSDecimalNumberExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NSDecimalNumberExtensions.swift; sourceTree = ""; }; + 28A4E605F118FDFF037ACD0C2F7FA3CD /* Yahoo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Yahoo.swift; sourceTree = ""; }; 3D3CEE659D9C1D3DEA521E896D331964 /* Pods-Custom Money-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-Custom Money-umbrella.h"; sourceTree = ""; }; 3D699C1DA947CA5DBF82BE8927112AC0 /* ValueCoding.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = ValueCoding.modulemap; sourceTree = ""; }; 3F972EB6AED7000E61962C751DD7165D /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -108,15 +111,18 @@ 4C1460F12F695C031F6228E5D1C63C9F /* SwiftyJSON.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = SwiftyJSON.xcconfig; sourceTree = ""; }; 4F003A917BF6D1C4FBA4D94B06C30179 /* ResultType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ResultType.swift; path = Result/ResultType.swift; sourceTree = ""; }; 50DFB978AB699248C726E034F1B3B42F /* ValueCoding.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ValueCoding.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 597CFBA87C75BE144B401FCC1EC5C927 /* NSDecimalExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NSDecimalExtensions.swift; sourceTree = ""; }; 5C29D8E4CA9E4CF9452CBCB9F8D56071 /* ValueCoding.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ValueCoding.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 6555ECBB6D5CDDE1EA197618BD3509AD /* Support.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Support.swift; sourceTree = ""; }; 65E593BAC0D422045A94607A9C0A277E /* ValueCoding-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ValueCoding-umbrella.h"; sourceTree = ""; }; - 6C83A0ED4B948E127B8A02BBD7F0A9BA /* Currency.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Currency.swift; sourceTree = ""; }; 71224125016483CBA4B84EA93DFD15CB /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 73CBCFF08B4E8BC27DCC0D5E90E976EA /* DecimalNumberType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DecimalNumberType.swift; sourceTree = ""; }; 765CD792203F037EA7D0D97B135C395A /* ValueCoding.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = ValueCoding.xcconfig; sourceTree = ""; }; 77FD247247D6D3CDBF638A9DB0EBDB4E /* SwiftyJSON.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SwiftyJSON.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7D56F281EDF6E7A4ED5627141F4E4DA2 /* Pods_Custom_Money.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Custom_Money.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 838F4AEA7BF1F57F0BE06B347D822D97 /* OpenExchangeRates.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = OpenExchangeRates.swift; sourceTree = ""; }; + 87218D77D4395E00D6D9170F8AFF291B /* Bitcoin.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Bitcoin.swift; sourceTree = ""; }; 8912AF1B024C1949E8DB3ECC403C4AE2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; + 8D811F4EED15D28415AF31F21F637295 /* Decimal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Decimal.swift; sourceTree = ""; }; 91C4C71A43800346A8BACEA8E5B05DA5 /* Money-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Money-umbrella.h"; sourceTree = ""; }; 94291E74B2ABBA056AD28AD1873DD8E3 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 946FC5A04C491594712C2DB0468A8E59 /* Pods-Custom Money-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-Custom Money-frameworks.sh"; sourceTree = ""; }; @@ -126,15 +132,16 @@ 9F8525B17F44112BA10D136F7F6C4089 /* ValueCoding-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "ValueCoding-prefix.pch"; sourceTree = ""; }; A26E7BC45299526E4063BB4C61816580 /* Money.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Money.framework; sourceTree = BUILT_PRODUCTS_DIR; }; A6DD5137FE8F22C2424D946F7E8D8D68 /* Pods-Custom Money-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-Custom Money-acknowledgements.markdown"; sourceTree = ""; }; - AFDAC51BCA9CA51E45E8E3EFF1115DC6 /* Autogenerated.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Autogenerated.swift; sourceTree = ""; }; B54A2AA14A7640E4A9B85F662D37A7D6 /* SwiftyJSON.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = SwiftyJSON.modulemap; sourceTree = ""; }; B5E95FBF4C047EA6401BB7B12E42A8B7 /* ValueCoding-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "ValueCoding-dummy.m"; sourceTree = ""; }; - B6A0B230AA93987BDA716F0FEBDCDA0E /* NSDecimalExtensions.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = NSDecimalExtensions.swift; sourceTree = ""; }; + B5EEF7A612BFA3D083C868A79762FB39 /* Money.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Money.swift; sourceTree = ""; }; + B8EEB490E417287676508AF49225E2B9 /* Autogenerated.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Autogenerated.swift; sourceTree = ""; }; BA6428E9F66FD5A23C0A2E06ED26CD2F /* Podfile */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; C31FCA3CC32B1FFB7E577A3FD7C8BDC8 /* SwiftyJSON.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = SwiftyJSON.swift; path = Source/SwiftyJSON.swift; sourceTree = ""; }; C3461681C9E35896A154A3D8722352D1 /* Pods-Custom Money-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-Custom Money-acknowledgements.plist"; sourceTree = ""; }; C4B98152CC246208D533CBEB9CD23E8C /* Money-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Money-prefix.pch"; sourceTree = ""; }; C6AD9E331A620215773EDAE3D38920CB /* Pods-Custom Money.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Custom Money.release.xcconfig"; sourceTree = ""; }; + C6E8271D7B956774CA6CD37674C3999C /* DecimalNumberType.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = DecimalNumberType.swift; sourceTree = ""; }; CCB9149D7C1AAA968AE461BDB9D1EEE8 /* Result.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Result.swift; path = Result/Result.swift; sourceTree = ""; }; D0F97F33A29F47BC32D7EBD2E18FAB2D /* Money.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Money.xcconfig; sourceTree = ""; }; D1FC653D131B20022B75023F33F250B9 /* Result.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Result.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -146,53 +153,52 @@ DF6284F39323D79B75BEEB8C366DE87C /* Pods-Custom Money.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-Custom Money.debug.xcconfig"; sourceTree = ""; }; E2CDFCF407B3970A3F2FD3C19CCA4CE7 /* SwiftyJSON-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "SwiftyJSON-dummy.m"; sourceTree = ""; }; ED5BC5B78EBB608AE95556AC64F2F724 /* ValueCoding.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ValueCoding.swift; path = ValueCoding/ValueCoding.swift; sourceTree = ""; }; - ED82986EB832C433BA892182F89597C6 /* Support.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Support.swift; sourceTree = ""; }; + EFF73AD3A7CF0FBE9BC94AEAC37858DD /* FX.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = FX.swift; sourceTree = ""; }; F158272DDE3E68231F6FE2A3DEB56C4E /* Result-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Result-umbrella.h"; sourceTree = ""; }; - F3E2C607AAC7546F5DA1FF6E1D936464 /* Decimal.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; path = Decimal.swift; sourceTree = ""; }; F50C4C662DD8A2616FF07C3827D2AAC0 /* Pods-Custom Money.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = "sourcecode.module-map"; path = "Pods-Custom Money.modulemap"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - 287993008FC38E134DDEC5ABE9076EC2 /* Frameworks */ = { + 063817B9347F8D64E119A7E71C814B32 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 01F1F11219565EEDB994774F5458DBCC /* Foundation.framework in Frameworks */, + A235DAAECF32771AAA2A866446349A80 /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 36E3CCD4791DA18A6646ECD589D9FA62 /* Frameworks */ = { + 2E34BE03E627006D15ADEA6C163BA5D0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - E8240E78A8B0F6B8EFD560880C1B7EA2 /* Foundation.framework in Frameworks */, - 8E429C0288212DAB30AD1C19DD92D176 /* Result.framework in Frameworks */, - D6564B72044D33B29B1ABCF62936AFF2 /* SwiftyJSON.framework in Frameworks */, - AE4219A42AA8CC10780AFC8B8603DEC7 /* ValueCoding.framework in Frameworks */, + F485847EBE24151C05EE62DCE7204EAF /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 3AFBB1C75257342FF231054380286529 /* Frameworks */ = { + 4716E670998219B6B6EB4A7AB3211D1C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 3F1E9A6F32C74A0E158DF5FD355FDADD /* Foundation.framework in Frameworks */, + 35575A63DB40EB8EC8BFD8189093A5DB /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 3B577FA4015B3AA4F0642D89BC36EF20 /* Frameworks */ = { + A973EBD95D75EA357A1572FC46D8517C /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - A5D79197F9C87AA12A55CF321D39FD9E /* Foundation.framework in Frameworks */, + 4F31C9D988EDAA919718FC3BD4CDD785 /* Foundation.framework in Frameworks */, + 31E645E979F3A5B089FCD8DEC7A3536E /* Result.framework in Frameworks */, + EDA2FDCE4DBBD0C20B3C52525812F335 /* SwiftyJSON.framework in Frameworks */, + C664644B24E321B0A4A8568F929E69D8 /* ValueCoding.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; - 4716E670998219B6B6EB4A7AB3211D1C /* Frameworks */ = { + EA5D97503478433CA914EEEB041FB4A0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 35575A63DB40EB8EC8BFD8189093A5DB /* Foundation.framework in Frameworks */, + 479158A06CDB3BB92C679F966E9D9E9E /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -208,17 +214,6 @@ path = ValueCoding; sourceTree = ""; }; - 1C7CAFC5D20189D4E6E712868550FB26 /* Decimal */ = { - isa = PBXGroup; - children = ( - F3E2C607AAC7546F5DA1FF6E1D936464 /* Decimal.swift */, - 73CBCFF08B4E8BC27DCC0D5E90E976EA /* DecimalNumberType.swift */, - B6A0B230AA93987BDA716F0FEBDCDA0E /* NSDecimalExtensions.swift */, - 3816C7DAA3910FD77039D0F101813083 /* NSDecimalNumberExtensions.swift */, - ); - path = Decimal; - sourceTree = ""; - }; 37FC7D49E06169F9EEE81FBA6366BDB9 /* Pods-Custom Money */ = { isa = PBXGroup; children = ( @@ -250,13 +245,35 @@ 5CEE22C08342643D21F896926A007B93 /* Money */ = { isa = PBXGroup; children = ( - A4426877A6400E8A0EF97526D9013EAE /* Money */, + 8AA0F47E58ABAF246515E19B4535F66B /* Money */, 88ECEAF82072CCAC7F028BBF483E773D /* Support Files */, ); name = Money; path = ../../..; sourceTree = ""; }; + 6C7887F173D1B299B79CDAABD19D2704 /* FX */ = { + isa = PBXGroup; + children = ( + 87218D77D4395E00D6D9170F8AFF291B /* Bitcoin.swift */, + EFF73AD3A7CF0FBE9BC94AEAC37858DD /* FX.swift */, + 838F4AEA7BF1F57F0BE06B347D822D97 /* OpenExchangeRates.swift */, + 28A4E605F118FDFF037ACD0C2F7FA3CD /* Yahoo.swift */, + ); + path = FX; + sourceTree = ""; + }; + 7B3DE46407420792449B7AADF7768E63 /* Decimal */ = { + isa = PBXGroup; + children = ( + 8D811F4EED15D28415AF31F21F637295 /* Decimal.swift */, + C6E8271D7B956774CA6CD37674C3999C /* DecimalNumberType.swift */, + 597CFBA87C75BE144B401FCC1EC5C927 /* NSDecimalExtensions.swift */, + 212F2F7938CA183DECE52229884F8877 /* NSDecimalNumberExtensions.swift */, + ); + path = Decimal; + sourceTree = ""; + }; 7CD8DE1FA9C24B39D42EAA6BE52E7E30 /* Products */ = { isa = PBXGroup; children = ( @@ -323,15 +340,15 @@ path = "Examples/Custom Money/Pods/Target Support Files/Money"; sourceTree = ""; }; - A4426877A6400E8A0EF97526D9013EAE /* Money */ = { + 8AA0F47E58ABAF246515E19B4535F66B /* Money */ = { isa = PBXGroup; children = ( - AFDAC51BCA9CA51E45E8E3EFF1115DC6 /* Autogenerated.swift */, - 6C83A0ED4B948E127B8A02BBD7F0A9BA /* Currency.swift */, - 21ADF1E6DF190AAE9E0330490E4C3CF4 /* FX.swift */, - 03F95EC7386DACBA19CC5260381AADDE /* Money.swift */, - ED82986EB832C433BA892182F89597C6 /* Support.swift */, - 1C7CAFC5D20189D4E6E712868550FB26 /* Decimal */, + B8EEB490E417287676508AF49225E2B9 /* Autogenerated.swift */, + 196613FD4A9A760DD899B3999B10DE39 /* Currency.swift */, + B5EEF7A612BFA3D083C868A79762FB39 /* Money.swift */, + 6555ECBB6D5CDDE1EA197618BD3509AD /* Support.swift */, + 7B3DE46407420792449B7AADF7768E63 /* Decimal */, + 6C7887F173D1B299B79CDAABD19D2704 /* FX */, ); path = Money; sourceTree = ""; @@ -407,56 +424,56 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - 6E4808B6DCEFB9C7F269EFD1C1EC9C1E /* Headers */ = { + 121AD303FE4E01089C531A97FD809397 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 78191570D151CEFFE5779A818A10D273 /* ValueCoding-umbrella.h in Headers */, + B97D98FFAAA3C8A163AFDA70C5AAF75C /* SwiftyJSON-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 6F9A0A9EDDAC4636E3474534015A7AEC /* Headers */ = { + 22E1441E18750994A84E7B0403907CBC /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - AB72AD9AEBAF9D656831C0593CB00F2C /* Money-umbrella.h in Headers */, + 80810DBE1DF76ECAAABA97CC92B7FC97 /* ValueCoding-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 8269C693AE9B0FAA04EE2300F9720E28 /* Headers */ = { + 76EC7561AE8C1FCEC260E5BA53821228 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 09F8C9409DF28C51561C0D4BCBDB7426 /* Pods-Custom Money-umbrella.h in Headers */, + 554CF5A8F13DEE08C7DB61AF96C42E2A /* Result-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - 92E11BD2A7982BE9DBED7211BC4F5139 /* Headers */ = { + 77C659239C7FD869381366BA007B3567 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - B0590FC08FA8208B3D4A3F1C3B3D231F /* SwiftyJSON-umbrella.h in Headers */, + 0217EDAB41BE6D83A68B4A2339BBA762 /* Money-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; - A1104E3A762FB90D79396269FE488BF5 /* Headers */ = { + 8269C693AE9B0FAA04EE2300F9720E28 /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 5E7CE62AF1775A4C8F8CE4336708FACF /* Result-umbrella.h in Headers */, + 09F8C9409DF28C51561C0D4BCBDB7426 /* Pods-Custom Money-umbrella.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - 3162227A40407035A6B7783E8DF419C0 /* Result */ = { + 335D5C3164D7294DB478331EF58A0C4F /* Result */ = { isa = PBXNativeTarget; - buildConfigurationList = 5157FB6DF5F40D1480DE27E6F4F6F192 /* Build configuration list for PBXNativeTarget "Result" */; + buildConfigurationList = 81F73A5B96E10FC3CD393C5AF6B23B20 /* Build configuration list for PBXNativeTarget "Result" */; buildPhases = ( - 511CC0195ACB2D26498CE4C92918E8EB /* Sources */, - 3B577FA4015B3AA4F0642D89BC36EF20 /* Frameworks */, - A1104E3A762FB90D79396269FE488BF5 /* Headers */, + 5B6AFD100B8B127EAAA9008096C2259C /* Sources */, + 2E34BE03E627006D15ADEA6C163BA5D0 /* Frameworks */, + 76EC7561AE8C1FCEC260E5BA53821228 /* Headers */, ); buildRules = ( ); @@ -467,13 +484,13 @@ productReference = D619B7641BF35CCD0B69F64DE1F3B98A /* Result.framework */; productType = "com.apple.product-type.framework"; }; - 392A4CAB83070A6D2BFD53A02DBF3F3A /* ValueCoding */ = { + 5112C7EBB0119AC3BA1E726F52B37099 /* ValueCoding */ = { isa = PBXNativeTarget; - buildConfigurationList = 6E0CE741A92A61C488DE040CED3E085F /* Build configuration list for PBXNativeTarget "ValueCoding" */; + buildConfigurationList = 2F3A813139924F1A5E5B2011370475B6 /* Build configuration list for PBXNativeTarget "ValueCoding" */; buildPhases = ( - 78A6B0DF6F273EBFC464152AEE8880F4 /* Sources */, - 287993008FC38E134DDEC5ABE9076EC2 /* Frameworks */, - 6E4808B6DCEFB9C7F269EFD1C1EC9C1E /* Headers */, + FC98ED70CA8B7B1AB9B1B0C865B55999 /* Sources */, + 063817B9347F8D64E119A7E71C814B32 /* Frameworks */, + 22E1441E18750994A84E7B0403907CBC /* Headers */, ); buildRules = ( ); @@ -484,62 +501,62 @@ productReference = 50DFB978AB699248C726E034F1B3B42F /* ValueCoding.framework */; productType = "com.apple.product-type.framework"; }; - 72F679D7EC35E44212F7DDF30676E432 /* SwiftyJSON */ = { + B63DBF20C97F25D4F844CB4BDFE4527A /* Pods-Custom Money */ = { isa = PBXNativeTarget; - buildConfigurationList = C1B846582E915B3960C2BB7D63A45E25 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */; + buildConfigurationList = 37A41A6B9185E59239BFB81D6353E1CF /* Build configuration list for PBXNativeTarget "Pods-Custom Money" */; buildPhases = ( - 3DD5417794C8371AC8C5C0E14D09B015 /* Sources */, - 3AFBB1C75257342FF231054380286529 /* Frameworks */, - 92E11BD2A7982BE9DBED7211BC4F5139 /* Headers */, + 9939AE9FAD1EEC366F8358A7D92606F6 /* Sources */, + 4716E670998219B6B6EB4A7AB3211D1C /* Frameworks */, + 8269C693AE9B0FAA04EE2300F9720E28 /* Headers */, ); buildRules = ( ); dependencies = ( + 6A5AB7BA465846DD13A7288647AE3D64 /* PBXTargetDependency */, + 5296D6953C077C85AFCB563124192C7D /* PBXTargetDependency */, + 14EE644027DDF28E4652404B99E3BE47 /* PBXTargetDependency */, + DBB46D880EEEB766A474B6074D4B98DF /* PBXTargetDependency */, ); - name = SwiftyJSON; - productName = SwiftyJSON; - productReference = DC0E8FE128B75E4AF4C971D16E94076E /* SwiftyJSON.framework */; + name = "Pods-Custom Money"; + productName = "Pods-Custom Money"; + productReference = 7D56F281EDF6E7A4ED5627141F4E4DA2 /* Pods_Custom_Money.framework */; productType = "com.apple.product-type.framework"; }; - 7B7DCF1E0AA248CEB9ECEDA271F769CF /* Money */ = { + DCEA67B24DDEA58F2608D2A7E29EC0AE /* Money */ = { isa = PBXNativeTarget; - buildConfigurationList = 08A005D3FEAC46D266B6125A996C5566 /* Build configuration list for PBXNativeTarget "Money" */; + buildConfigurationList = 5CADF911B07C597448EFF422ABDB3FDE /* Build configuration list for PBXNativeTarget "Money" */; buildPhases = ( - C85EDC555633733F4044486EE937639F /* Sources */, - 36E3CCD4791DA18A6646ECD589D9FA62 /* Frameworks */, - 6F9A0A9EDDAC4636E3474534015A7AEC /* Headers */, + C8934663EB4AE0B4929444533C9EF220 /* Sources */, + A973EBD95D75EA357A1572FC46D8517C /* Frameworks */, + 77C659239C7FD869381366BA007B3567 /* Headers */, ); buildRules = ( ); dependencies = ( - 74A7EEF02148E28896373E011E00E453 /* PBXTargetDependency */, - CEFCEFA0EC8DC38BA5F89A533919F966 /* PBXTargetDependency */, - 593A557A4013D60694292A73EE435A48 /* PBXTargetDependency */, + C8DCBE089958260D159D5C44647F41CF /* PBXTargetDependency */, + D407F2C774D39C8178BBAB3740391322 /* PBXTargetDependency */, + D89098397CC9BDCF51043D6F04F96FF9 /* PBXTargetDependency */, ); name = Money; productName = Money; productReference = A26E7BC45299526E4063BB4C61816580 /* Money.framework */; productType = "com.apple.product-type.framework"; }; - B63DBF20C97F25D4F844CB4BDFE4527A /* Pods-Custom Money */ = { + E1BC6514E856EA889BE33605FA7C661A /* SwiftyJSON */ = { isa = PBXNativeTarget; - buildConfigurationList = 37A41A6B9185E59239BFB81D6353E1CF /* Build configuration list for PBXNativeTarget "Pods-Custom Money" */; + buildConfigurationList = FDDDB1E35279A6D3923344153846DF57 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */; buildPhases = ( - 9939AE9FAD1EEC366F8358A7D92606F6 /* Sources */, - 4716E670998219B6B6EB4A7AB3211D1C /* Frameworks */, - 8269C693AE9B0FAA04EE2300F9720E28 /* Headers */, + 8928033D360B3AD2E4332DBAE9791D67 /* Sources */, + EA5D97503478433CA914EEEB041FB4A0 /* Frameworks */, + 121AD303FE4E01089C531A97FD809397 /* Headers */, ); buildRules = ( ); dependencies = ( - 6A5AB7BA465846DD13A7288647AE3D64 /* PBXTargetDependency */, - 5296D6953C077C85AFCB563124192C7D /* PBXTargetDependency */, - 14EE644027DDF28E4652404B99E3BE47 /* PBXTargetDependency */, - DBB46D880EEEB766A474B6074D4B98DF /* PBXTargetDependency */, ); - name = "Pods-Custom Money"; - productName = "Pods-Custom Money"; - productReference = 7D56F281EDF6E7A4ED5627141F4E4DA2 /* Pods_Custom_Money.framework */; + name = SwiftyJSON; + productName = SwiftyJSON; + productReference = DC0E8FE128B75E4AF4C971D16E94076E /* SwiftyJSON.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -563,66 +580,69 @@ projectDirPath = ""; projectRoot = ""; targets = ( - 7B7DCF1E0AA248CEB9ECEDA271F769CF /* Money */, + DCEA67B24DDEA58F2608D2A7E29EC0AE /* Money */, B63DBF20C97F25D4F844CB4BDFE4527A /* Pods-Custom Money */, - 3162227A40407035A6B7783E8DF419C0 /* Result */, - 72F679D7EC35E44212F7DDF30676E432 /* SwiftyJSON */, - 392A4CAB83070A6D2BFD53A02DBF3F3A /* ValueCoding */, + 335D5C3164D7294DB478331EF58A0C4F /* Result */, + E1BC6514E856EA889BE33605FA7C661A /* SwiftyJSON */, + 5112C7EBB0119AC3BA1E726F52B37099 /* ValueCoding */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ - 3DD5417794C8371AC8C5C0E14D09B015 /* Sources */ = { + 5B6AFD100B8B127EAAA9008096C2259C /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 9A09B11207C1722543A88B81FD18E43D /* SwiftyJSON-dummy.m in Sources */, - B0BD516593207CE2DFF82F7428C2C0A9 /* SwiftyJSON.swift in Sources */, + F796D5F5B55CE16B1311C41299E86D0B /* Result-dummy.m in Sources */, + 435ED888CA386BA222E288B1CC8574F5 /* Result.swift in Sources */, + 84964756F22AEE07130A328DC0143EFA /* ResultType.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 511CC0195ACB2D26498CE4C92918E8EB /* Sources */ = { + 8928033D360B3AD2E4332DBAE9791D67 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7A64F6E65EEA7AD7BA15349E04A6C17E /* Result-dummy.m in Sources */, - FCAC7A169DF92F4B209A2B4ADF0CEECC /* Result.swift in Sources */, - 30A618A1BC51A7D95D17A2067B21ACF0 /* ResultType.swift in Sources */, + 16CC6804DA661658124C44577F2953E4 /* SwiftyJSON-dummy.m in Sources */, + 5637E947D3756585ECF976E01D38CC8A /* SwiftyJSON.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 78A6B0DF6F273EBFC464152AEE8880F4 /* Sources */ = { + 9939AE9FAD1EEC366F8358A7D92606F6 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3CD1D2DD10E273F86707E96E8BDB06AA /* ValueCoding-dummy.m in Sources */, - 40CD08E83AB8406EFF6DAD723DFA3AC3 /* ValueCoding.swift in Sources */, + 46B661B9D41457BFE21F2618E7CCC4E0 /* Pods-Custom Money-dummy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - 9939AE9FAD1EEC366F8358A7D92606F6 /* Sources */ = { + C8934663EB4AE0B4929444533C9EF220 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 46B661B9D41457BFE21F2618E7CCC4E0 /* Pods-Custom Money-dummy.m in Sources */, + 84E7501479AACC41E67BB26817D9639D /* Autogenerated.swift in Sources */, + 7E586FC96883817FC458B25FA91BD2CE /* Bitcoin.swift in Sources */, + 1F6A8EBF7DF1DD625F8CCDB7AED2F528 /* Currency.swift in Sources */, + F0A058EFFE6ECEE169C2B53704C78963 /* Decimal.swift in Sources */, + F896F74FA7879D4F61DB699A27BF844D /* DecimalNumberType.swift in Sources */, + 7FAE343617CB65AE9CB6BF5CFE4F1134 /* FX.swift in Sources */, + BFD28C75A55F161255F8F1C263D779F7 /* Money-dummy.m in Sources */, + 4F45ED652CD2AAFDE8AEE11F158045B5 /* Money.swift in Sources */, + 685E5FA73478973B4D2184A91E4E7FF8 /* NSDecimalExtensions.swift in Sources */, + ECB837E114BC2BC4BBE280CE6CAE9BF4 /* NSDecimalNumberExtensions.swift in Sources */, + 8752AAACF89C0D05BAFAC976E18B43B5 /* OpenExchangeRates.swift in Sources */, + CD10415D334D475BA55049F7F5027125 /* Support.swift in Sources */, + 4C88E376338108DCA576487003CFC800 /* Yahoo.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; - C85EDC555633733F4044486EE937639F /* Sources */ = { + FC98ED70CA8B7B1AB9B1B0C865B55999 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - FC421BD763CC47A66D9082814D727889 /* Autogenerated.swift in Sources */, - 6E4DBC7F136D4F38ECD0AE3CB83A0676 /* Currency.swift in Sources */, - F099E4D77161FCDE09092A1EFE073689 /* Decimal.swift in Sources */, - 5749D741D8442D600F69E17C2E0C571E /* DecimalNumberType.swift in Sources */, - 563C2572D3B5DF7896E7626C05F0CE11 /* FX.swift in Sources */, - 205DE9495F6E98279A553429FDDF15B6 /* Money-dummy.m in Sources */, - 75DB6DD279AC32DEEE23F40E91029761 /* Money.swift in Sources */, - 33F7DE75B0812B10F67D0420C6D71510 /* NSDecimalExtensions.swift in Sources */, - DF62EA9ACF4A13DAF30D77D29FF0A664 /* NSDecimalNumberExtensions.swift in Sources */, - 591F03157805EB971E8A5D69F6F5112F /* Support.swift in Sources */, + ADF9BB52327C5FFC7A934CDA0EE843D9 /* ValueCoding-dummy.m in Sources */, + 92290889D67198C19057765E18109214 /* ValueCoding.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -632,51 +652,51 @@ 14EE644027DDF28E4652404B99E3BE47 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftyJSON; - target = 72F679D7EC35E44212F7DDF30676E432 /* SwiftyJSON */; + target = E1BC6514E856EA889BE33605FA7C661A /* SwiftyJSON */; targetProxy = 36023380F037B6AB8D4492DCA3A27CD5 /* PBXContainerItemProxy */; }; 5296D6953C077C85AFCB563124192C7D /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Result; - target = 3162227A40407035A6B7783E8DF419C0 /* Result */; + target = 335D5C3164D7294DB478331EF58A0C4F /* Result */; targetProxy = 41F272EA7F75CA2CEBC8E35579A501C9 /* PBXContainerItemProxy */; }; - 593A557A4013D60694292A73EE435A48 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - name = ValueCoding; - target = 392A4CAB83070A6D2BFD53A02DBF3F3A /* ValueCoding */; - targetProxy = FC9033D9680B4E91FEC3E2DAD8E754F3 /* PBXContainerItemProxy */; - }; 6A5AB7BA465846DD13A7288647AE3D64 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Money; - target = 7B7DCF1E0AA248CEB9ECEDA271F769CF /* Money */; + target = DCEA67B24DDEA58F2608D2A7E29EC0AE /* Money */; targetProxy = 1DFE2A02B5C6BDFE88F8CA3DFB0FC286 /* PBXContainerItemProxy */; }; - 74A7EEF02148E28896373E011E00E453 /* PBXTargetDependency */ = { + C8DCBE089958260D159D5C44647F41CF /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Result; - target = 3162227A40407035A6B7783E8DF419C0 /* Result */; - targetProxy = 1CA2F65C195043637C90F2888D138A77 /* PBXContainerItemProxy */; + target = 335D5C3164D7294DB478331EF58A0C4F /* Result */; + targetProxy = 20E2555ABC7481F293A5C37138092ED3 /* PBXContainerItemProxy */; }; - CEFCEFA0EC8DC38BA5F89A533919F966 /* PBXTargetDependency */ = { + D407F2C774D39C8178BBAB3740391322 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = SwiftyJSON; - target = 72F679D7EC35E44212F7DDF30676E432 /* SwiftyJSON */; - targetProxy = 7AA052775F912BADEC1FFCBF37B0CE8F /* PBXContainerItemProxy */; + target = E1BC6514E856EA889BE33605FA7C661A /* SwiftyJSON */; + targetProxy = 5C0A58B226E00A3E1A7328A37E81607F /* PBXContainerItemProxy */; + }; + D89098397CC9BDCF51043D6F04F96FF9 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = ValueCoding; + target = 5112C7EBB0119AC3BA1E726F52B37099 /* ValueCoding */; + targetProxy = 39651D11DAC97EA2B23D906D0DE433D1 /* PBXContainerItemProxy */; }; DBB46D880EEEB766A474B6074D4B98DF /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = ValueCoding; - target = 392A4CAB83070A6D2BFD53A02DBF3F3A /* ValueCoding */; + target = 5112C7EBB0119AC3BA1E726F52B37099 /* ValueCoding */; targetProxy = A8D7D5C5D4B2B0DBEA7CD9A1C6CA1131 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 155B87FE08E3E94C4A3224D3CA34A844 /* Release */ = { + 1A5C3AB79FFAD473C53D2FF59AD706F0 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 4C1460F12F695C031F6228E5D1C63C9F /* SwiftyJSON.xcconfig */; + baseConfigurationReference = DF6284F39323D79B75BEEB8C366DE87C /* Pods-Custom Money.debug.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; @@ -685,25 +705,29 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/SwiftyJSON/Info.plist"; + INFOPLIST_FILE = "Target Support Files/Pods-Custom Money/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/SwiftyJSON/SwiftyJSON.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = SwiftyJSON; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-Custom Money/Pods-Custom Money.modulemap"; + MTL_ENABLE_DEBUG_INFO = YES; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_NAME = Pods_Custom_Money; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Release; + name = Debug; }; - 1A5C3AB79FFAD473C53D2FF59AD706F0 /* Debug */ = { + 1E313C554CA678E5FBA9A8A9C495E979 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = DF6284F39323D79B75BEEB8C366DE87C /* Pods-Custom Money.debug.xcconfig */; + baseConfigurationReference = 765CD792203F037EA7D0D97B135C395A /* ValueCoding.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; @@ -712,27 +736,23 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - INFOPLIST_FILE = "Target Support Files/Pods-Custom Money/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/ValueCoding/ValueCoding-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ValueCoding/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-Custom Money/Pods-Custom Money.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_NAME = Pods_Custom_Money; + MODULEMAP_FILE = "Target Support Files/ValueCoding/ValueCoding.modulemap"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = ValueCoding; SDKROOT = iphoneos; SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; - name = Debug; + name = Release; }; - 4995DDF9C7DA0EB2DAD7955EC6C7E16D /* Debug */ = { + 229C78DF249EF56E40117D412B509267 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4C1460F12F695C031F6228E5D1C63C9F /* SwiftyJSON.xcconfig */; buildSettings = { @@ -790,9 +810,9 @@ }; name = Release; }; - 69CB76F5C7AB28E540D9920F52F6ADF0 /* Debug */ = { + 6D83889271DAA877F278D48348131D8F /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D0F97F33A29F47BC32D7EBD2E18FAB2D /* Money.xcconfig */; + baseConfigurationReference = 269178DAB03BE95581C9933E5AD7BA5E /* Result.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; @@ -801,14 +821,14 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/Money/Money-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Money/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Result/Result-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Result/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Money/Money.modulemap"; + MODULEMAP_FILE = "Target Support Files/Result/Result.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Money; + PRODUCT_NAME = Result; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -818,9 +838,9 @@ }; name = Debug; }; - 6BD90311D0271248CD69AE34E2D3F023 /* Debug */ = { + A9EE419C41A292FD5A5DA55A849AE598 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 269178DAB03BE95581C9933E5AD7BA5E /* Result.xcconfig */; + baseConfigurationReference = 765CD792203F037EA7D0D97B135C395A /* ValueCoding.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; @@ -829,14 +849,14 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/Result/Result-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Result/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/ValueCoding/ValueCoding-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/ValueCoding/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Result/Result.modulemap"; + MODULEMAP_FILE = "Target Support Files/ValueCoding/ValueCoding.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Result; + PRODUCT_NAME = ValueCoding; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -846,9 +866,48 @@ }; name = Debug; }; - 86F21C46C5F12EAC4936A18B3B5C6484 /* Debug */ = { + C074F63C9EE7CB4D8C618390A32CEC35 /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 765CD792203F037EA7D0D97B135C395A /* ValueCoding.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.1; + ONLY_ACTIVE_ARCH = YES; + STRIP_INSTALLED_PRODUCT = NO; + SYMROOT = "${SRCROOT}/../build"; + }; + name = Debug; + }; + CE64D1FCE295EEFA2910197082F6093A /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = D0F97F33A29F47BC32D7EBD2E18FAB2D /* Money.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; @@ -857,14 +916,14 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/ValueCoding/ValueCoding-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/ValueCoding/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Money/Money-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Money/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/ValueCoding/ValueCoding.modulemap"; + MODULEMAP_FILE = "Target Support Files/Money/Money.modulemap"; MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = ValueCoding; + PRODUCT_NAME = Money; SDKROOT = iphoneos; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; @@ -874,9 +933,9 @@ }; name = Debug; }; - 8EFFC1C125424EA89B82CFAB194229AB /* Release */ = { + D07B644BAB1ACA7BF4FE0B94D2AD6A1E /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = D0F97F33A29F47BC32D7EBD2E18FAB2D /* Money.xcconfig */; + baseConfigurationReference = 4C1460F12F695C031F6228E5D1C63C9F /* SwiftyJSON.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; @@ -885,14 +944,14 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/Money/Money-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Money/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/SwiftyJSON/SwiftyJSON-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/SwiftyJSON/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Money/Money.modulemap"; + MODULEMAP_FILE = "Target Support Files/SwiftyJSON/SwiftyJSON.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Money; + PRODUCT_NAME = SwiftyJSON; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; @@ -901,9 +960,9 @@ }; name = Release; }; - BDA4AFECD66C51EC5CB5FD10E522DB96 /* Release */ = { + D2CE3C2E7FAA5512165C714F952EEE9F /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 765CD792203F037EA7D0D97B135C395A /* ValueCoding.xcconfig */; + baseConfigurationReference = 269178DAB03BE95581C9933E5AD7BA5E /* Result.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; @@ -912,14 +971,14 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/ValueCoding/ValueCoding-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/ValueCoding/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Result/Result-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Result/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/ValueCoding/ValueCoding.modulemap"; + MODULEMAP_FILE = "Target Support Files/Result/Result.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = ValueCoding; + PRODUCT_NAME = Result; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; @@ -928,45 +987,6 @@ }; name = Release; }; - C074F63C9EE7CB4D8C618390A32CEC35 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; - ONLY_ACTIVE_ARCH = YES; - STRIP_INSTALLED_PRODUCT = NO; - SYMROOT = "${SRCROOT}/../build"; - }; - name = Debug; - }; E43846B588E1892F3093F3B7082B6DFB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1001,9 +1021,9 @@ }; name = Release; }; - E94DE46C3FE758FA6C0D60E3649FA006 /* Release */ = { + FE0E40BE653EF899426B04460F58B2B8 /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 269178DAB03BE95581C9933E5AD7BA5E /* Result.xcconfig */; + baseConfigurationReference = D0F97F33A29F47BC32D7EBD2E18FAB2D /* Money.xcconfig */; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CURRENT_PROJECT_VERSION = 1; @@ -1012,14 +1032,14 @@ DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Target Support Files/Result/Result-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Result/Info.plist"; + GCC_PREFIX_HEADER = "Target Support Files/Money/Money-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Money/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 9.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Result/Result.modulemap"; + MODULEMAP_FILE = "Target Support Files/Money/Money.modulemap"; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = Result; + PRODUCT_NAME = Money; SDKROOT = iphoneos; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; @@ -1031,20 +1051,20 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - 08A005D3FEAC46D266B6125A996C5566 /* Build configuration list for PBXNativeTarget "Money" */ = { + 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - 69CB76F5C7AB28E540D9920F52F6ADF0 /* Debug */, - 8EFFC1C125424EA89B82CFAB194229AB /* Release */, + C074F63C9EE7CB4D8C618390A32CEC35 /* Debug */, + E43846B588E1892F3093F3B7082B6DFB /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { + 2F3A813139924F1A5E5B2011370475B6 /* Build configuration list for PBXNativeTarget "ValueCoding" */ = { isa = XCConfigurationList; buildConfigurations = ( - C074F63C9EE7CB4D8C618390A32CEC35 /* Debug */, - E43846B588E1892F3093F3B7082B6DFB /* Release */, + A9EE419C41A292FD5A5DA55A849AE598 /* Debug */, + 1E313C554CA678E5FBA9A8A9C495E979 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -1058,29 +1078,29 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 5157FB6DF5F40D1480DE27E6F4F6F192 /* Build configuration list for PBXNativeTarget "Result" */ = { + 5CADF911B07C597448EFF422ABDB3FDE /* Build configuration list for PBXNativeTarget "Money" */ = { isa = XCConfigurationList; buildConfigurations = ( - 6BD90311D0271248CD69AE34E2D3F023 /* Debug */, - E94DE46C3FE758FA6C0D60E3649FA006 /* Release */, + CE64D1FCE295EEFA2910197082F6093A /* Debug */, + FE0E40BE653EF899426B04460F58B2B8 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 6E0CE741A92A61C488DE040CED3E085F /* Build configuration list for PBXNativeTarget "ValueCoding" */ = { + 81F73A5B96E10FC3CD393C5AF6B23B20 /* Build configuration list for PBXNativeTarget "Result" */ = { isa = XCConfigurationList; buildConfigurations = ( - 86F21C46C5F12EAC4936A18B3B5C6484 /* Debug */, - BDA4AFECD66C51EC5CB5FD10E522DB96 /* Release */, + 6D83889271DAA877F278D48348131D8F /* Debug */, + D2CE3C2E7FAA5512165C714F952EEE9F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - C1B846582E915B3960C2BB7D63A45E25 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */ = { + FDDDB1E35279A6D3923344153846DF57 /* Build configuration list for PBXNativeTarget "SwiftyJSON" */ = { isa = XCConfigurationList; buildConfigurations = ( - 4995DDF9C7DA0EB2DAD7955EC6C7E16D /* Debug */, - 155B87FE08E3E94C4A3224D3CA34A844 /* Release */, + 229C78DF249EF56E40117D412B509267 /* Debug */, + D07B644BAB1ACA7BF4FE0B94D2AD6A1E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/Examples/Custom Money/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Money.xcscheme b/Examples/Custom Money/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Money.xcscheme index 99bfe2a..a7d04d4 100644 --- a/Examples/Custom Money/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Money.xcscheme +++ b/Examples/Custom Money/Pods/Pods.xcodeproj/xcshareddata/xcschemes/Money.xcscheme @@ -14,7 +14,7 @@ buildForArchiving = "YES"> diff --git a/Examples/Custom Money/Pods/Target Support Files/Money/Info.plist b/Examples/Custom Money/Pods/Target Support Files/Money/Info.plist index 6974542..01903d7 100644 --- a/Examples/Custom Money/Pods/Target Support Files/Money/Info.plist +++ b/Examples/Custom Money/Pods/Target Support Files/Money/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0.0 + 1.1.0 CFBundleSignature ???? CFBundleVersion diff --git a/Money.podspec b/Money.podspec index 9ce012a..568362e 100644 --- a/Money.podspec +++ b/Money.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Money" - s.version = "1.1.0" + s.version = "1.2.0" s.summary = "Swift types for working with Money." s.description = <<-DESC @@ -21,7 +21,7 @@ Pod::Spec.new do |s| s.osx.deployment_target = '10.10' s.tvos.deployment_target = '9.0' s.watchos.deployment_target = '2.0' - s.source_files = ['Money/*.swift', 'Money/Decimal/*.swift'] + s.source_files = ['Money/*.swift', 'Money/Decimal/*.swift', 'Money/FX/*.swift'] s.dependency 'ValueCoding' s.dependency 'Result', '0.6.0-beta.6' diff --git a/Money.xcodeproj/project.pbxproj b/Money.xcodeproj/project.pbxproj index 36405dc..d84b606 100644 --- a/Money.xcodeproj/project.pbxproj +++ b/Money.xcodeproj/project.pbxproj @@ -21,6 +21,39 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 653E84051BEF9B860020FF0E /* BitcoinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84041BEF9B860020FF0E /* BitcoinTests.swift */; }; + 653E84061BEF9B860020FF0E /* BitcoinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84041BEF9B860020FF0E /* BitcoinTests.swift */; }; + 653E84071BEF9B860020FF0E /* BitcoinTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84041BEF9B860020FF0E /* BitcoinTests.swift */; }; + 653E84161BEFC4BE0020FF0E /* CEX.IO BTCUSD.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */; }; + 653E84171BEFC4BE0020FF0E /* CEX.IO BTCUSD.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */; }; + 653E84181BEFC4BE0020FF0E /* CEX.IO BTCUSD.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */; }; + 653E84191BEFC4BE0020FF0E /* CEX.IO BTCUSD.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */; }; + 653E841A1BEFC4D40020FF0E /* CEX.IO BTCUSD.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */; }; + 653E841B1BEFC4DA0020FF0E /* CEX.IO BTCUSD.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */; }; + 653E841C1BEFC4E00020FF0E /* CEX.IO BTCUSD.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */; }; + 653E841E1BEFCF720020FF0E /* CEX.IO USDBTC.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */; }; + 653E841F1BEFCF720020FF0E /* CEX.IO USDBTC.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */; }; + 653E84201BEFCF720020FF0E /* CEX.IO USDBTC.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */; }; + 653E84211BEFCF720020FF0E /* CEX.IO USDBTC.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */; }; + 653E84221BEFCF7F0020FF0E /* CEX.IO USDBTC.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */; }; + 653E84231BEFCF860020FF0E /* CEX.IO USDBTC.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */; }; + 653E84241BEFCF8A0020FF0E /* CEX.IO USDBTC.json in Resources */ = {isa = PBXBuildFile; fileRef = 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */; }; + 653E84281BEFF1050020FF0E /* Bitcoin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84261BEFF1050020FF0E /* Bitcoin.swift */; }; + 653E84291BEFF1050020FF0E /* Bitcoin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84261BEFF1050020FF0E /* Bitcoin.swift */; }; + 653E842A1BEFF1050020FF0E /* Bitcoin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84261BEFF1050020FF0E /* Bitcoin.swift */; }; + 653E842B1BEFF1050020FF0E /* Bitcoin.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84261BEFF1050020FF0E /* Bitcoin.swift */; }; + 653E842C1BEFF1050020FF0E /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84271BEFF1050020FF0E /* FX.swift */; }; + 653E842D1BEFF1050020FF0E /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84271BEFF1050020FF0E /* FX.swift */; }; + 653E842E1BEFF1050020FF0E /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84271BEFF1050020FF0E /* FX.swift */; }; + 653E842F1BEFF1050020FF0E /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84271BEFF1050020FF0E /* FX.swift */; }; + 653E84311BEFF11F0020FF0E /* Yahoo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84301BEFF11F0020FF0E /* Yahoo.swift */; }; + 653E84321BEFF11F0020FF0E /* Yahoo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84301BEFF11F0020FF0E /* Yahoo.swift */; }; + 653E84331BEFF11F0020FF0E /* Yahoo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84301BEFF11F0020FF0E /* Yahoo.swift */; }; + 653E84341BEFF11F0020FF0E /* Yahoo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84301BEFF11F0020FF0E /* Yahoo.swift */; }; + 653E84361BEFF12E0020FF0E /* OpenExchangeRates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84351BEFF12E0020FF0E /* OpenExchangeRates.swift */; }; + 653E84371BEFF12E0020FF0E /* OpenExchangeRates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84351BEFF12E0020FF0E /* OpenExchangeRates.swift */; }; + 653E84381BEFF12E0020FF0E /* OpenExchangeRates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84351BEFF12E0020FF0E /* OpenExchangeRates.swift */; }; + 653E84391BEFF12E0020FF0E /* OpenExchangeRates.swift in Sources */ = {isa = PBXBuildFile; fileRef = 653E84351BEFF12E0020FF0E /* OpenExchangeRates.swift */; }; 6557F4C71BEB7F32003CD2BF /* ValueCoding.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6557F4C61BEB7F32003CD2BF /* ValueCoding.framework */; }; 6557F4C91BEB7F3D003CD2BF /* ValueCoding.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6557F4C81BEB7F3D003CD2BF /* ValueCoding.framework */; }; 6557F4CB1BEB7F46003CD2BF /* ValueCoding.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 6557F4CA1BEB7F46003CD2BF /* ValueCoding.framework */; }; @@ -80,10 +113,6 @@ 65A876E61BE79A9400E26F22 /* Autogenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657C0B1B1BE164B700CDB873 /* Autogenerated.swift */; }; 65A876E71BE79A9500E26F22 /* Autogenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657C0B1B1BE164B700CDB873 /* Autogenerated.swift */; }; 65A876E81BE79A9600E26F22 /* Autogenerated.swift in Sources */ = {isa = PBXBuildFile; fileRef = 657C0B1B1BE164B700CDB873 /* Autogenerated.swift */; }; - 65A876EF1BE7B88F00E26F22 /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A876EE1BE7B88F00E26F22 /* FX.swift */; }; - 65A876F01BE7B88F00E26F22 /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A876EE1BE7B88F00E26F22 /* FX.swift */; }; - 65A876F11BE7B88F00E26F22 /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A876EE1BE7B88F00E26F22 /* FX.swift */; }; - 65A876F21BE7B88F00E26F22 /* FX.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A876EE1BE7B88F00E26F22 /* FX.swift */; }; 65A876F41BE7D1A100E26F22 /* FXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A876F31BE7D1A100E26F22 /* FXTests.swift */; }; 65A876F51BE7D1A100E26F22 /* FXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A876F31BE7D1A100E26F22 /* FXTests.swift */; }; 65A876F61BE7D1A100E26F22 /* FXTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 65A876F31BE7D1A100E26F22 /* FXTests.swift */; }; @@ -164,6 +193,13 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 653E84041BEF9B860020FF0E /* BitcoinTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BitcoinTests.swift; sourceTree = ""; }; + 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "CEX.IO BTCUSD.json"; path = "DVR Cassettes/CEX.IO BTCUSD.json"; sourceTree = ""; }; + 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = "CEX.IO USDBTC.json"; path = "DVR Cassettes/CEX.IO USDBTC.json"; sourceTree = ""; }; + 653E84261BEFF1050020FF0E /* Bitcoin.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Bitcoin.swift; sourceTree = ""; }; + 653E84271BEFF1050020FF0E /* FX.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FX.swift; sourceTree = ""; }; + 653E84301BEFF11F0020FF0E /* Yahoo.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Yahoo.swift; sourceTree = ""; }; + 653E84351BEFF12E0020FF0E /* OpenExchangeRates.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenExchangeRates.swift; sourceTree = ""; }; 6557F4C61BEB7F32003CD2BF /* ValueCoding.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ValueCoding.framework; path = Carthage/Build/iOS/ValueCoding.framework; sourceTree = ""; }; 6557F4C81BEB7F3D003CD2BF /* ValueCoding.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ValueCoding.framework; path = Carthage/Build/watchOS/ValueCoding.framework; sourceTree = ""; }; 6557F4CA1BEB7F46003CD2BF /* ValueCoding.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ValueCoding.framework; path = Carthage/Build/tvOS/ValueCoding.framework; sourceTree = ""; }; @@ -189,7 +225,6 @@ 658863BC1BEA34ED003482ED /* DVR.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DVR.framework; path = Carthage/Build/iOS/DVR.framework; sourceTree = ""; }; 658863BE1BEA3514003482ED /* DVR.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = DVR.framework; path = Carthage/Build/Mac/DVR.framework; sourceTree = ""; }; 65A876D61BE6491800E26F22 /* Generate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = Generate.swift; path = "Supporting Files/Generate.swift"; sourceTree = SOURCE_ROOT; }; - 65A876EE1BE7B88F00E26F22 /* FX.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FX.swift; sourceTree = ""; }; 65A876F31BE7D1A100E26F22 /* FXTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FXTests.swift; sourceTree = ""; }; 65B92AD31BE0E4A700F82024 /* Money.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Money.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 65B92ADD1BE0E4A700F82024 /* Money-iOSTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Money-iOSTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -281,6 +316,17 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 653E84251BEFF1050020FF0E /* FX */ = { + isa = PBXGroup; + children = ( + 653E84261BEFF1050020FF0E /* Bitcoin.swift */, + 653E84271BEFF1050020FF0E /* FX.swift */, + 653E84301BEFF11F0020FF0E /* Yahoo.swift */, + 653E84351BEFF12E0020FF0E /* OpenExchangeRates.swift */, + ); + path = FX; + sourceTree = ""; + }; 6557F4D31BEB8720003CD2BF /* Decimal */ = { isa = PBXGroup; children = ( @@ -320,12 +366,12 @@ 65B92B301BE0E51E00F82024 /* Money */ = { isa = PBXGroup; children = ( - 6557F4D31BEB8720003CD2BF /* Decimal */, 657C0B1B1BE164B700CDB873 /* Autogenerated.swift */, 657C0B0D1BE10D2700CDB873 /* Currency.swift */, - 65A876EE1BE7B88F00E26F22 /* FX.swift */, 65B92B421BE0F93F00F82024 /* Money.swift */, 657C0B121BE1211900CDB873 /* Support.swift */, + 6557F4D31BEB8720003CD2BF /* Decimal */, + 653E84251BEFF1050020FF0E /* FX */, ); path = Money; sourceTree = ""; @@ -347,13 +393,14 @@ children = ( 65B92B381BE0E69500F82024 /* Info.plist */, 658863B61BEA2B0B003482ED /* Troll.png */, + 653E84041BEF9B860020FF0E /* BitcoinTests.swift */, 65D305511BE8E8210032D99F /* DecimalTests.swift */, 656409441BEAB5DC00F82B4D /* FXOpenExchangeRatesTests.swift */, 65A876F31BE7D1A100E26F22 /* FXTests.swift */, 656409401BEAABCA00F82B4D /* FXYahooTests.swift */, 65B92B391BE0E69500F82024 /* MoneyTests.swift */, - 6557F4E81BEB924D003CD2BF /* NSDecimalTests.swift */, 6557F4EC1BEB97AC003CD2BF /* NSDecimalNumberTests.swift */, + 6557F4E81BEB924D003CD2BF /* NSDecimalTests.swift */, 65FC56411BEA667300727556 /* Network Responses */, ); path = Tests; @@ -383,6 +430,8 @@ 65FC56411BEA667300727556 /* Network Responses */ = { isa = PBXGroup; children = ( + 653E841D1BEFCF720020FF0E /* CEX.IO USDBTC.json */, + 653E84151BEFC4BE0020FF0E /* CEX.IO BTCUSD.json */, 6557F4F01BEBC5C1003CD2BF /* Yahoo GBPUSD.json */, 656409481BEAB88700F82B4D /* OpenExchangeRates.org USDEUR.json */, ); @@ -625,6 +674,8 @@ buildActionMask = 2147483647; files = ( 65B92B3A1BE0E69500F82024 /* Info.plist in Resources */, + 653E841E1BEFCF720020FF0E /* CEX.IO USDBTC.json in Resources */, + 653E84161BEFC4BE0020FF0E /* CEX.IO BTCUSD.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -632,6 +683,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84221BEFCF7F0020FF0E /* CEX.IO USDBTC.json in Resources */, + 653E841A1BEFC4D40020FF0E /* CEX.IO BTCUSD.json in Resources */, 6557F4F11BEBC5CD003CD2BF /* Yahoo GBPUSD.json in Resources */, 656409491BEAB89400F82B4D /* OpenExchangeRates.org USDEUR.json in Resources */, 658863B91BEA2B26003482ED /* Troll.png in Resources */, @@ -642,6 +695,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84171BEFC4BE0020FF0E /* CEX.IO BTCUSD.json in Resources */, + 653E841F1BEFCF720020FF0E /* CEX.IO USDBTC.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -649,6 +704,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84181BEFC4BE0020FF0E /* CEX.IO BTCUSD.json in Resources */, + 653E84201BEFCF720020FF0E /* CEX.IO USDBTC.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -656,6 +713,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84231BEFCF860020FF0E /* CEX.IO USDBTC.json in Resources */, + 653E841B1BEFC4DA0020FF0E /* CEX.IO BTCUSD.json in Resources */, 6557F4F21BEBC5D2003CD2BF /* Yahoo GBPUSD.json in Resources */, 6564094A1BEAB89B00F82B4D /* OpenExchangeRates.org USDEUR.json in Resources */, 658863BA1BEA2B2C003482ED /* Troll.png in Resources */, @@ -666,6 +725,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84191BEFC4BE0020FF0E /* CEX.IO BTCUSD.json in Resources */, + 653E84211BEFCF720020FF0E /* CEX.IO USDBTC.json in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -673,6 +734,8 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84241BEFCF8A0020FF0E /* CEX.IO USDBTC.json in Resources */, + 653E841C1BEFC4E00020FF0E /* CEX.IO BTCUSD.json in Resources */, 6557F4F31BEBC5D7003CD2BF /* Yahoo GBPUSD.json in Resources */, 6564094B1BEAB8A100F82B4D /* OpenExchangeRates.org USDEUR.json in Resources */, 658863BB1BEA2B30003482ED /* Troll.png in Resources */, @@ -758,15 +821,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84311BEFF11F0020FF0E /* Yahoo.swift in Sources */, 657C0B0E1BE10D2700CDB873 /* Currency.swift in Sources */, + 653E84361BEFF12E0020FF0E /* OpenExchangeRates.swift in Sources */, 65B92B431BE0F93F00F82024 /* Money.swift in Sources */, 6557F4E41BEB8850003CD2BF /* NSDecimalExtensions.swift in Sources */, + 653E842C1BEFF1050020FF0E /* FX.swift in Sources */, 65A876E51BE79A9300E26F22 /* Autogenerated.swift in Sources */, 6557F4DA1BEB8720003CD2BF /* NSDecimalNumberExtensions.swift in Sources */, 6557F4DF1BEB8737003CD2BF /* DecimalNumberType.swift in Sources */, + 653E84281BEFF1050020FF0E /* Bitcoin.swift in Sources */, 6557F4D61BEB8720003CD2BF /* Decimal.swift in Sources */, 657C0B131BE1211900CDB873 /* Support.swift in Sources */, - 65A876EF1BE7B88F00E26F22 /* FX.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -774,6 +840,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84051BEF9B860020FF0E /* BitcoinTests.swift in Sources */, 65B92B3F1BE0E72700F82024 /* MoneyTests.swift in Sources */, 65D305521BE8E8210032D99F /* DecimalTests.swift in Sources */, 6557F4E91BEB924D003CD2BF /* NSDecimalTests.swift in Sources */, @@ -788,15 +855,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84321BEFF11F0020FF0E /* Yahoo.swift in Sources */, 657C0B0F1BE10D2700CDB873 /* Currency.swift in Sources */, + 653E84371BEFF12E0020FF0E /* OpenExchangeRates.swift in Sources */, 65B92B441BE0F93F00F82024 /* Money.swift in Sources */, 6557F4E51BEB8850003CD2BF /* NSDecimalExtensions.swift in Sources */, + 653E842D1BEFF1050020FF0E /* FX.swift in Sources */, 65A876E61BE79A9400E26F22 /* Autogenerated.swift in Sources */, 6557F4DB1BEB8720003CD2BF /* NSDecimalNumberExtensions.swift in Sources */, 6557F4E01BEB8737003CD2BF /* DecimalNumberType.swift in Sources */, + 653E84291BEFF1050020FF0E /* Bitcoin.swift in Sources */, 6557F4D71BEB8720003CD2BF /* Decimal.swift in Sources */, 657C0B141BE1211900CDB873 /* Support.swift in Sources */, - 65A876F01BE7B88F00E26F22 /* FX.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -804,15 +874,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84331BEFF11F0020FF0E /* Yahoo.swift in Sources */, 657C0B101BE10D2700CDB873 /* Currency.swift in Sources */, + 653E84381BEFF12E0020FF0E /* OpenExchangeRates.swift in Sources */, 65B92B451BE0F93F00F82024 /* Money.swift in Sources */, 6557F4E61BEB8850003CD2BF /* NSDecimalExtensions.swift in Sources */, + 653E842E1BEFF1050020FF0E /* FX.swift in Sources */, 65A876E71BE79A9500E26F22 /* Autogenerated.swift in Sources */, 6557F4DC1BEB8720003CD2BF /* NSDecimalNumberExtensions.swift in Sources */, 6557F4E11BEB8737003CD2BF /* DecimalNumberType.swift in Sources */, + 653E842A1BEFF1050020FF0E /* Bitcoin.swift in Sources */, 6557F4D81BEB8720003CD2BF /* Decimal.swift in Sources */, 657C0B151BE1211900CDB873 /* Support.swift in Sources */, - 65A876F11BE7B88F00E26F22 /* FX.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -820,6 +893,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84061BEF9B860020FF0E /* BitcoinTests.swift in Sources */, 65B92B401BE0E72800F82024 /* MoneyTests.swift in Sources */, 65D305531BE8E8210032D99F /* DecimalTests.swift in Sources */, 6557F4EA1BEB924D003CD2BF /* NSDecimalTests.swift in Sources */, @@ -834,15 +908,18 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84341BEFF11F0020FF0E /* Yahoo.swift in Sources */, 657C0B111BE10D2700CDB873 /* Currency.swift in Sources */, + 653E84391BEFF12E0020FF0E /* OpenExchangeRates.swift in Sources */, 65B92B461BE0F93F00F82024 /* Money.swift in Sources */, 6557F4E71BEB8850003CD2BF /* NSDecimalExtensions.swift in Sources */, + 653E842F1BEFF1050020FF0E /* FX.swift in Sources */, 65A876E81BE79A9600E26F22 /* Autogenerated.swift in Sources */, 6557F4DD1BEB8720003CD2BF /* NSDecimalNumberExtensions.swift in Sources */, 6557F4E21BEB8737003CD2BF /* DecimalNumberType.swift in Sources */, + 653E842B1BEFF1050020FF0E /* Bitcoin.swift in Sources */, 6557F4D91BEB8720003CD2BF /* Decimal.swift in Sources */, 657C0B161BE1211900CDB873 /* Support.swift in Sources */, - 65A876F21BE7B88F00E26F22 /* FX.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -850,6 +927,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 653E84071BEF9B860020FF0E /* BitcoinTests.swift in Sources */, 65B92B411BE0E72900F82024 /* MoneyTests.swift in Sources */, 65D305541BE8E8210032D99F /* DecimalTests.swift in Sources */, 6557F4EB1BEB924D003CD2BF /* NSDecimalTests.swift in Sources */, diff --git a/Money/Currency.swift b/Money/Currency.swift index 9726930..1f58752 100644 --- a/Money/Currency.swift +++ b/Money/Currency.swift @@ -156,4 +156,8 @@ public struct Currency { } +// MARK: - Crypto Currencies + +public protocol CryptoCurrencyType: CurrencyType { } + diff --git a/Money/Decimal/Decimal.swift b/Money/Decimal/Decimal.swift index ad6ad28..1db29c5 100644 --- a/Money/Decimal/Decimal.swift +++ b/Money/Decimal/Decimal.swift @@ -196,7 +196,6 @@ public final class _DecimalCoder: NSObject, } - // TODO: - Move these into DecimalNumberType extension NSNumberFormatter { diff --git a/Money/FX/Bitcoin.swift b/Money/FX/Bitcoin.swift new file mode 100644 index 0000000..6856e7c --- /dev/null +++ b/Money/FX/Bitcoin.swift @@ -0,0 +1,169 @@ +// +// Bitcoin.swift +// Money +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Daniel Thorpe +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import Result +import SwiftyJSON + + +// MARK: - Bitcoin Currency + +protocol BitcoinCurrencyType: CryptoCurrencyType { } + +extension Currency { + + /** + # Currency.XBT + This is the ISO 4217 currency code, however at the moment + it is unofficial. + */ + public struct XBT: BitcoinCurrencyType { + public static let code = "XBT" + /// unicode \u{20bf} was accepted as the Bitcoin currency + /// symbol in November + public static let symbol = "Ƀ" + /// The smallest unit of Bitcoin is the Satoshi + /// - see: https://en.bitcoin.it/wiki/Satoshi_(unit) + public static let scale: Int = 8 + public static let formatter: NSNumberFormatter = { + let fmtr = NSNumberFormatter() + fmtr.numberStyle = .CurrencyStyle + fmtr.maximumFractionDigits = scale + fmtr.currencySymbol = symbol + return fmtr + }() + } + + /** + # Currency.BTC + This is the common code used for Bitcoin, although it can never become + the ISO standard as BT is the country code for Bhutan. + */ + public struct BTC: BitcoinCurrencyType { + public static let code = "BTC" + public static let symbol = Currency.XBT.symbol + public static let scale = Currency.XBT.scale + public static let formatter = Currency.XBT.formatter + } +} + +public typealias XBT = _Money +public typealias BTC = _Money + + +// MARK - cex.io FX + +public protocol CEXSupportedFiatCurrencyType: CurrencyType { + static var cex_commissionPercentage: BankersDecimal { get } +} + +extension Currency.USD: CEXSupportedFiatCurrencyType { + public static let cex_commissionPercentage: BankersDecimal = 0.2 +} + +extension Currency.EUR: CEXSupportedFiatCurrencyType { + public static let cex_commissionPercentage: BankersDecimal = 0.2 +} + +extension Currency.RUB: CEXSupportedFiatCurrencyType { + public static let cex_commissionPercentage: BankersDecimal = 0 +} + +struct _CEXBuy: CryptoCurrencyMarketTransactionType { + typealias BaseMoney = Base + typealias CounterMoney = BTC + typealias FiatCurrency = Base.Currency + static var transactionKind: CurrencyMarketTransactionKind { return .Buy } +} + +struct _CEXSell: CryptoCurrencyMarketTransactionType { + typealias BaseMoney = BTC + typealias CounterMoney = Counter + typealias FiatCurrency = Counter.Currency + static var transactionKind: CurrencyMarketTransactionKind { return .Sell } +} + +class _CEX: FXRemoteProvider, FXRemoteProviderType { + + static func name() -> String { + return "CEX.IO \(BaseMoney.Currency.code)\(CounterMoney.Currency.code)" + } + + static func request() -> NSURLRequest { + let url = NSURL(string: "https://cex.io/api/convert/\(BTC.Currency.code)/\(T.FiatCurrency.code)") + let request = NSMutableURLRequest(URL: url!) + request.HTTPMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + let data = try! JSON(["amnt": Double(1.0)]).rawData() + request.HTTPBody = data + return request + } + + static func quoteFromNetworkResult(result: Result<(NSData?, NSURLResponse?), NSError>) -> Result { + return result.analysis( + + ifSuccess: { data, response in + + guard let data = data else { + return Result(error: .NoData) + } + + let json = JSON(data: data) + + if json.isEmpty { + return Result(error: .InvalidData(data)) + } + + guard let rateLiteral = json["amnt"].double else { + return Result(error: .RateNotFound(name())) + } + + let rate: BankersDecimal + + switch T.transactionKind { + case .Buy: + rate = BankersDecimal(floatLiteral: rateLiteral).reciprocal + case .Sell: + rate = BankersDecimal(floatLiteral: rateLiteral) + } + + return Result(value: FXQuote(rate: rate, percentage: T.FiatCurrency.cex_commissionPercentage)) + }, + + ifFailure: { error in + return Result(error: .NetworkError(error)) + } + ) + } +} + +public final class CEXBuy: _CEX<_CEXBuy> { } +public final class CEXSell: _CEX<_CEXSell> { } + + + + + diff --git a/Money/FX.swift b/Money/FX/FX.swift similarity index 57% rename from Money/FX.swift rename to Money/FX/FX.swift index 300f92a..cde32e3 100644 --- a/Money/FX.swift +++ b/Money/FX/FX.swift @@ -30,6 +30,8 @@ import ValueCoding import Result import SwiftyJSON +// MARK: - Currency Markets + /** # MoneyPairType Used to represent currency pairs. @@ -45,31 +47,52 @@ public protocol MoneyPairType { typealias CounterMoney: MoneyType } +public enum CurrencyMarketTransactionKind { + case Buy, Sell +} + +public protocol CurrencyMarketTransactionType: MoneyPairType { + static var transactionKind: CurrencyMarketTransactionKind { get } +} + +public protocol CryptoCurrencyMarketTransactionType: CurrencyMarketTransactionType { + typealias FiatCurrency: CurrencyType +} + // MARK: - FX Types /** # Quote - The minimum interface required to perform a foreign - currency exchange. + Represents an FX quote with a rate and commision + percentage. By default the percentage is 0. */ -public class FXQuote: NSObject, NSCoding { +public struct FXQuote { /// The exchange rate, stored as a `BankersDecimal`. public let rate: BankersDecimal + /// The commission as a percentage, e.g. 0.2 => 0.2% + public let percentage: BankersDecimal + /** - Construct with the rate + Construct with a rate and commission percentage (defaults to + zero). + + - parameter rate: a `BankersDecimal`. + - parameter percentage: a `BankersDecimal`. + - returns: a `FXQuote` */ - public init(rate: BankersDecimal) { + public init(rate: BankersDecimal, percentage: BankersDecimal = 0) { self.rate = rate + self.percentage = percentage } - public required init?(coder aDecoder: NSCoder) { - rate = BankersDecimal.decode(aDecoder.decodeObjectForKey("rate"))! - } - - public func encodeWithCoder(aCoder: NSCoder) { - aCoder.encodeObject(rate.encoded, forKey: "rate") + /** + ## Calculate the commission. + Taken as the ammount of the base currency. + */ + public func commission(base: B) -> B { + return (percentage / 100) * base } /** @@ -87,10 +110,44 @@ public class FXQuote: NSObject, NSCoding { can work just like the `Yahoo` one here. */ public func transactionValueForBaseValue(base: B) -> C { - return base.convertWithRate(rate) + return ((1 - (percentage / 100)) * base).convertWithRate(rate) + } +} + +public struct FXTransaction: MoneyPairType { + + public typealias BaseMoney = Base + public typealias CounterMoney = Counter + + public let base: BaseMoney + public let commission: BaseMoney + public let rate: BankersDecimal + public let counter: CounterMoney + + internal init(base: BaseMoney, commission: BaseMoney, rate: BankersDecimal, counter: CounterMoney) { + self.base = base + self.commission = commission + self.rate = rate + self.counter = counter + } + + public init(base: BaseMoney, quote: FXQuote) { + self.base = base + self.commission = quote.commission(base) + self.rate = quote.rate + self.counter = quote.transactionValueForBaseValue(base) } } + // MARK: - FX Provider Errors /** @@ -153,13 +210,21 @@ public protocol FXLocalProviderType: FXProviderType { static func quote() -> FXQuote } -extension FXLocalProviderType where BaseMoney.DecimalStorageType == BankersDecimal.DecimalStorageType, CounterMoney.DecimalStorageType == BankersDecimal.DecimalStorageType { +extension FXLocalProviderType where + BaseMoney.Coder: NSCoding, + BaseMoney.Coder.ValueType == BaseMoney, + BaseMoney.DecimalStorageType == BankersDecimal.DecimalStorageType, + CounterMoney.Coder: NSCoding, + CounterMoney.Coder.ValueType == CounterMoney, + CounterMoney.DecimalStorageType == BankersDecimal.DecimalStorageType { + + public typealias Transaction = FXTransaction /** This is the primary API used to determine for Foreign Exchange transactions. */ - public static func fx(base: BaseMoney) -> CounterMoney { - return base.convertWithRate(quote().rate) + public static func fx(base: BaseMoney) -> Transaction { + return Transaction(base: base, quote: quote()) } } @@ -223,10 +288,18 @@ extension FXRemoteProviderType { } } -extension FXRemoteProviderType where BaseMoney.DecimalStorageType == BankersDecimal.DecimalStorageType, CounterMoney.DecimalStorageType == BankersDecimal.DecimalStorageType { +extension FXRemoteProviderType where + BaseMoney.Coder: NSCoding, + BaseMoney.Coder.ValueType == BaseMoney, + BaseMoney.DecimalStorageType == BankersDecimal.DecimalStorageType, + CounterMoney.Coder: NSCoding, + CounterMoney.Coder.ValueType == CounterMoney, + CounterMoney.DecimalStorageType == BankersDecimal.DecimalStorageType { - internal static func fxFromQuoteWithBase(base: BaseMoney) -> FXQuote -> (BaseMoney, FXQuote, CounterMoney) { - return { (base, $0, $0.transactionValueForBaseValue(base)) } + public typealias Transaction = FXTransaction + + internal static func fxFromQuoteWithBase(base: BaseMoney) -> FXQuote -> Transaction { + return { Transaction(base: base, quote: $0) } } /** @@ -248,7 +321,7 @@ extension FXRemoteProviderType where BaseMoney.DecimalStorageType == BankersDeci base money, the quote, and the counter money, or `(BaseMoney, FXQuote, CounterMoney)`. - returns: an `NSURLSessionDataTask`. */ - public static func quote(base: BaseMoney, completion: Result<(BaseMoney, FXQuote, CounterMoney), FXError> -> Void) -> NSURLSessionDataTask { + public static func quote(base: BaseMoney, completion: Result -> Void) -> NSURLSessionDataTask { let client = FXServiceProviderNetworkClient(session: session()) let fxFromQuote = fxFromQuoteWithBase(base) return client.get(request(), adaptor: quoteFromNetworkResult) { completion($0.map(fxFromQuote)) } @@ -272,7 +345,7 @@ extension FXRemoteProviderType where BaseMoney.DecimalStorageType == BankersDeci - returns: an `NSURLSessionDataTask`. */ public static func fx(base: BaseMoney, completion: Result -> Void) -> NSURLSessionDataTask { - return quote(base) { completion($0.map { $0.2 }) } + return quote(base) { completion($0.map { $0.counter }) } } } @@ -300,208 +373,79 @@ public class FXRemoteProvider { public typealias CounterMoney = T } -// MARK: - Yahoo FX Service Provider - -/** - # Yahoo FX - This type uses Yahoo's Currency Converter. E.g. - - It is generic over two `MoneyType`s, and is only - used as a type - there is no initializer. - - ```swift - Yahoo.fx(100) { jpy in - print("\(jpy)") // is a Result - } - ``` +// MARK: - ValueCoding -*/ -public final class Yahoo: FXRemoteProvider, FXRemoteProviderType { +extension FXQuote: ValueCoding { + public typealias Coder = FXQuoteCoder +} - /** - Access the name of the FX provider (e.g. "Yahoo USDEUR" - - - returns: a `String`. - */ - public static func name() -> String { - return "Yahoo \(Base.Currency.code)\(Counter.Currency.code)" +public final class FXQuoteCoder: NSObject, NSCoding, CodingType { + enum Keys: String { + case Rate = "rate" + case Percentage = "percentage" } - /** - Constructs the `NSURLRequest` to Yahoo's currency convertor service. + public let value: FXQuote - - returns: a `NSURLRequest`. - */ - public static func request() -> NSURLRequest { - return NSURLRequest(URL: NSURL(string: "https://download.finance.yahoo.com/d/quotes.csv?s=\(BaseMoney.Currency.code)\(CounterMoney.Currency.code)=X&f=nl1")!) + public required init(_ v: FXQuote) { + value = v } - /** - This function is used to map the network result into a quote. - - - paramter result: the network result, represented as `Result` where - the value, T, is a tuple of data and response. The error, E, is an `NSError`. - - returns: a `Result`. - */ - public static func quoteFromNetworkResult(result: Result<(NSData?, NSURLResponse?), NSError>) -> Result { - return result.analysis( - - ifSuccess: { data, response in - - guard let data = data else { - return Result(error: .NoData) - } - - guard let str = String(data: data, encoding: NSUTF8StringEncoding) else { - return Result(error: .InvalidData(data)) - } - - let components = str.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).componentsSeparatedByString(",") - - if components.count < 2 { - return Result(error: .InvalidData(data)) - } - - guard let rate = Double(components[1]) else { - return Result(error: .RateNotFound(str)) - } - - return Result(value: FXQuote(rate: BankersDecimal(floatLiteral: rate))) - }, + public init?(coder aDecoder: NSCoder) { + let rate = BankersDecimal.decode(aDecoder.decodeObjectForKey(Keys.Rate.rawValue)) + let percentage = BankersDecimal.decode(aDecoder.decodeObjectForKey(Keys.Percentage.rawValue)) + value = FXQuote(rate: rate!, percentage: percentage!) + } - ifFailure: { error in - return Result(error: .NetworkError(error)) - } - ) + public func encodeWithCoder(aCoder: NSCoder) { + aCoder.encodeObject(value.rate.encoded, forKey: Keys.Rate.rawValue) + aCoder.encodeObject(value.percentage.encoded, forKey: Keys.Percentage.rawValue) } } -// MARK: - Open Exchange Rates FX Service Provider - -/** - # Open Exchange Rates - Open Exchange Rates (OER) is a popular FX provider, - which does have a "forever free" service, which will - only return rates for all supported currencies with - USD as the base currency. - - Paid for access allows specification of the base & - counter currency. - - All access requires an "app_id", even the forever - free one. - - This protocol defines a type which can return the - app_id. Therefore, consumers should define their - own type which conforms, and then using whatever - mechanism you want, return your OER app_id. I - recommend using something like [CocoaPod Keys](https://github.com/orta/cocoapods-keys) - - Lets say, you create this... - - - struct MyOpenExchangeRatesAppID: OpenExchangeRatesAppID { - static let app_id = "blarblarblarblar" - } - - Now, create subclasses of `_OpenExchangeRates` or - `_ForeverFreeOpenExchangeRates` depending on your access level. - - e.g. If you have a forever free app_id: - - - class OpenExchangeRates: _ForeverFreeOpenExchangeRates { } - - usage would then be like this: - - - let usd: USD = 100 - OpenExchangeRates.fx(usd) { result in - // etc, result will include the GBP exchanged for US$ 100 - } - - If you have paid for access to OpenExchangeRates then instead - create the following subclass: - - - class OpenExchangeRates: _OpenExchangeRates { } - - - see: [https://openexchangerates.org](https://openexchangerates.org) - - see: [CocoaPod Keys](https://github.com/orta/cocoapods-keys) +extension FXTransaction: ValueCoding { + public typealias Coder = FXTransactionCoder +} -*/ -public protocol OpenExchangeRatesAppID { - static var app_id: String { get } +private enum FXTransactionCoderKeys: String { + case Base = "base" + case Commission = "commission" + case Rate = "rate" + case Counter = "counter" } -/** - # Open Exchange Rates - Base class for OpenExchangeRates.org. See the docs above. +public final class FXTransactionCoder: NSObject, NSCoding, CodingType { - - see: `OpenExchangeRatesAppID` -*/ -public class _OpenExchangeRates: FXRemoteProvider, FXRemoteProviderType { + public let value: FXTransaction - public static func name() -> String { - return "OpenExchangeRates.org \(Base.Currency.code)\(Counter.Currency.code)" + public required init(_ v: FXTransaction) { + value = v } - public static func request() -> NSURLRequest { - var url = NSURL(string: "https://openexchangerates.org/api/latest.json?app_id=\(ID.app_id)")! - - switch BaseMoney.Currency.code { - case Currency.USD.code: - break - default: - url = url.URLByAppendingPathComponent("&base=\(BaseMoney.Currency.code)") - } - - return NSURLRequest(URL: url) + public init?(coder aDecoder: NSCoder) { + let base: Base? = Base.decode(aDecoder.decodeObjectForKey(FXTransactionCoderKeys.Base.rawValue)) + let rate = BankersDecimal.decode(aDecoder.decodeObjectForKey(FXTransactionCoderKeys.Rate.rawValue)) + let commission = Base.decode(aDecoder.decodeObjectForKey(FXTransactionCoderKeys.Commission.rawValue)) + let counter = Counter.decode(aDecoder.decodeObjectForKey(FXTransactionCoderKeys.Counter.rawValue)) + value = FXTransaction(base: base!, commission: commission!, rate: rate!, counter: counter!) } - public static func quoteFromNetworkResult(result: Result<(NSData?, NSURLResponse?), NSError>) -> Result { - return result.analysis( - - ifSuccess: { data, response in - - guard let data = data else { - return Result(error: .NoData) - } - - let json = JSON(data: data) - - if json.isEmpty { - return Result(error: .InvalidData(data)) - } - - guard let rate = json[["rates", CounterMoney.Currency.code]].double else { - return Result(error: .RateNotFound(name())) - } - - return Result(value: FXQuote(rate: BankersDecimal(floatLiteral: rate))) - }, - - ifFailure: { error in - return Result(error: .NetworkError(error)) - } - ) + public func encodeWithCoder(aCoder: NSCoder) { + aCoder.encodeObject(value.base.encoded, forKey: FXTransactionCoderKeys.Base.rawValue) + aCoder.encodeObject(value.rate.encoded, forKey: FXTransactionCoderKeys.Rate.rawValue) + aCoder.encodeObject(value.commission.encoded, forKey: FXTransactionCoderKeys.Commission.rawValue) + aCoder.encodeObject(value.counter.encoded, forKey: FXTransactionCoderKeys.Counter.rawValue) } } -/** - # Open Exchange Rates - Forever Free class for OpenExchangeRates.org. See the docs above. - - - see: `OpenExchangeRatesAppID` - */ -public class _ForeverFreeOpenExchangeRates: _OpenExchangeRates { } - - - - - - - public func ==(lhs: FXError, rhs: FXError) -> Bool { switch (lhs, rhs) { diff --git a/Money/FX/OpenExchangeRates.swift b/Money/FX/OpenExchangeRates.swift new file mode 100644 index 0000000..5a963ed --- /dev/null +++ b/Money/FX/OpenExchangeRates.swift @@ -0,0 +1,157 @@ +// +// OpenExchangeRates.swift +// Money +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Daniel Thorpe +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import ValueCoding +import Result +import SwiftyJSON + + +// MARK: - Open Exchange Rates FX Service Provider + +/** +# Open Exchange Rates +Open Exchange Rates (OER) is a popular FX provider, +which does have a "forever free" service, which will +only return rates for all supported currencies with +USD as the base currency. + +Paid for access allows specification of the base & +counter currency. + +All access requires an "app_id", even the forever +free one. + +This protocol defines a type which can return the +app_id. Therefore, consumers should define their +own type which conforms, and then using whatever +mechanism you want, return your OER app_id. I +recommend using something like [CocoaPod Keys](https://github.com/orta/cocoapods-keys) + +Lets say, you create this... + + +struct MyOpenExchangeRatesAppID: OpenExchangeRatesAppID { +static let app_id = "blarblarblarblar" +} + +Now, create subclasses of `_OpenExchangeRates` or +`_ForeverFreeOpenExchangeRates` depending on your access level. + +e.g. If you have a forever free app_id: + + +class OpenExchangeRates: _ForeverFreeOpenExchangeRates { } + +usage would then be like this: + + +let usd: USD = 100 +OpenExchangeRates.fx(usd) { result in +// etc, result will include the GBP exchanged for US$ 100 +} + +If you have paid for access to OpenExchangeRates then instead +create the following subclass: + + +class OpenExchangeRates: _OpenExchangeRates { } + +- see: [https://openexchangerates.org](https://openexchangerates.org) +- see: [CocoaPod Keys](https://github.com/orta/cocoapods-keys) + +*/ +public protocol OpenExchangeRatesAppID { + static var app_id: String { get } +} + +/** + # Open Exchange Rates + Base class for OpenExchangeRates.org. See the docs above. + + - see: `OpenExchangeRatesAppID` + */ +public class _OpenExchangeRates: FXRemoteProvider, FXRemoteProviderType { + + public static func name() -> String { + return "OpenExchangeRates.org \(Base.Currency.code)\(Counter.Currency.code)" + } + + public static func request() -> NSURLRequest { + var url = NSURL(string: "https://openexchangerates.org/api/latest.json?app_id=\(ID.app_id)")! + + switch BaseMoney.Currency.code { + case Currency.USD.code: + break + default: + url = url.URLByAppendingPathComponent("&base=\(BaseMoney.Currency.code)") + } + + return NSURLRequest(URL: url) + } + + public static func quoteFromNetworkResult(result: Result<(NSData?, NSURLResponse?), NSError>) -> Result { + return result.analysis( + + ifSuccess: { data, response in + + guard let data = data else { + return Result(error: .NoData) + } + + let json = JSON(data: data) + + if json.isEmpty { + return Result(error: .InvalidData(data)) + } + + guard let rate = json[["rates", CounterMoney.Currency.code]].double else { + return Result(error: .RateNotFound(name())) + } + + return Result(value: FXQuote(rate: BankersDecimal(floatLiteral: rate))) + }, + + ifFailure: { error in + return Result(error: .NetworkError(error)) + } + ) + } +} + +/** + # Open Exchange Rates + Forever Free class for OpenExchangeRates.org. See the docs above. + + - see: `OpenExchangeRatesAppID` + */ +public class _ForeverFreeOpenExchangeRates: _OpenExchangeRates { } + + + + + + diff --git a/Money/FX/Yahoo.swift b/Money/FX/Yahoo.swift new file mode 100644 index 0000000..c3eacb6 --- /dev/null +++ b/Money/FX/Yahoo.swift @@ -0,0 +1,107 @@ +// +// Yahoo.swift +// Money +// +// The MIT License (MIT) +// +// Copyright (c) 2015 Daniel Thorpe +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import Foundation +import ValueCoding +import Result +import SwiftyJSON + + +// MARK: - Yahoo FX Service Provider + +/** +# Yahoo FX +This type uses Yahoo's Currency Converter. E.g. + +It is generic over two `MoneyType`s, and is only +used as a type - there is no initializer. + +```swift +Yahoo.fx(100) { jpy in +print("\(jpy)") // is a Result +} +``` + +*/ +public final class Yahoo: FXRemoteProvider, FXRemoteProviderType { + + /** + Access the name of the FX provider (e.g. "Yahoo USDEUR") + + - returns: a `String`. + */ + public static func name() -> String { + return "Yahoo \(Base.Currency.code)\(Counter.Currency.code)" + } + + /** + Constructs the `NSURLRequest` to Yahoo's currency convertor service. + + - returns: a `NSURLRequest`. + */ + public static func request() -> NSURLRequest { + return NSURLRequest(URL: NSURL(string: "https://download.finance.yahoo.com/d/quotes.csv?s=\(BaseMoney.Currency.code)\(CounterMoney.Currency.code)=X&f=nl1")!) + } + + /** + This function is used to map the network result into a quote. + + - paramter result: the network result, represented as `Result` where + the value, T, is a tuple of data and response. The error, E, is an `NSError`. + - returns: a `Result`. + */ + public static func quoteFromNetworkResult(result: Result<(NSData?, NSURLResponse?), NSError>) -> Result { + return result.analysis( + + ifSuccess: { data, response in + + guard let data = data else { + return Result(error: .NoData) + } + + guard let str = String(data: data, encoding: NSUTF8StringEncoding) else { + return Result(error: .InvalidData(data)) + } + + let components = str.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()).componentsSeparatedByString(",") + + if components.count < 2 { + return Result(error: .InvalidData(data)) + } + + guard let rate = Double(components[1]) else { + return Result(error: .RateNotFound(str)) + } + + return Result(value: FXQuote(rate: BankersDecimal(floatLiteral: rate))) + }, + + ifFailure: { error in + return Result(error: .NetworkError(error)) + } + ) + } +} diff --git a/Money/Money.swift b/Money/Money.swift index f82e7fb..a869622 100644 --- a/Money/Money.swift +++ b/Money/Money.swift @@ -33,7 +33,7 @@ import ValueCoding `MoneyType` is a protocol which refines `DecimalNumberType`. It adds a generic type for the currency. */ -public protocol MoneyType: DecimalNumberType { +public protocol MoneyType: DecimalNumberType, ValueCoding { typealias Currency: CurrencyType /// Access the underlying decimal diff --git a/README.md b/README.md index f9ed2d4..cb007bc 100644 --- a/README.md +++ b/README.md @@ -70,15 +70,17 @@ The following code snippet represent a currency exchange using Yahoo’s currenc ```swift Yahoo.quote(100) { result in - if let (dollars, quote, euros) = result.value { - print("Exchanged \(dollars) into \(euros) with a rate of \(quote.rate)") + if let tx = result.value { + print("Exchanged \(tx.base) into \(tx.counter) with a rate of \(tx.rate) and \(tx.commission) commission.") } } ``` -> Exchanged US$ 100.00 into € 92.15 with a rate of 0.9215 +> Exchanged US$ 100.00 into € 93.09 with a rate of 0.93089 and US$ 0.00 commission. -The result, delivered asynchronously, uses [`Result`](http://github.com/antitypical/Result) to encapsulate either a tuple value `(BaseMoney, FXQuote, CounterMoney)` or an `FXError` value. Obviously, in real code - you’d need to check for errors ;) +The result, delivered asynchronously, uses [`Result`](http://github.com/antitypical/Result) to encapsulate either a `FXTransaction` or an `FXError` value. Obviously, in real code - you’d need to check for errors ;) + +`FXTransaction` is a generic type which captures the base and counter monies, the rate of the exchange, and any commission the FX service provider charged in the base currency. Currently `FXQuote` only supports percentage based commission. There is a neat convenience function which just returns the `CounterMoney` as its `Result` value type. @@ -88,8 +90,7 @@ Yahoo.fx(100) { euros in } ``` -> You got .Success(€ 92.15) - +> You got .Success(€ 93.09) ### Creating custom FX service providers @@ -135,9 +136,52 @@ public static func quoteFromNetworkResult(result: Result<(NSData?, NSURLResponse Note that the provider doesn’t need to perform any networking itself. It is all done by the framework. This is a deliberate architectural design as it makes it much easier to unit test the adaptor code. -Additionally FX APIs will be added shortly, -1. To calculate the reverse exchange, i.e. how many dollars would I need to get so many euros. -2. For the two (forward & reverse) exchanges, I’ll also add a `quote` function, which will return the `FXQuote` object. This might be useful if your app needs to persist the quote used for an exchange. +## Bitcoin + +Money has support for Bitcoin types, the popular `BTC` and the unofficial ISO 4217 currency code `XBT`. + +In [November 2015](http://www.coindesk.com/bitcoin-unicode-symbol-approval/), the Unicode consortium accepted U+20BF as the Bitcoin symbol. However, right now that means it is not available in Foundation. Therefore, currently the Bitcoin currency type(s) use Ƀ, which is also a popular symbol and available already within Unicode. + +To work with Bitcoin, use the following: + +```swift +let bitcoin: BTC = 0.1234_5678 +print(“You have \(bitcoin)”) +``` +> You have Ƀ0.12345678 + +Money has support for using [CEX.IO](https://cex.io)’s [trade api](https://cex.io/api) to support quotes of Bitcoin currency exchanges. CEX only supports `USD`, `EUR,` and `RUB` [fiat currencies](https://en.wikipedia.org/wiki/Fiat_money). + +It’s usage is a little bit different for a regular FX. To represent the purchase of Bitcoins use `CEXBuy` like this: + +```swift +CEXBuy.quote(100) { result in + if let tx = result.value { + print("\(tx.base) will buy \(tx.counter) at a rate of \(tx.rate) with \(tx.commission)") + } +} +``` +> US$ 100.00 will buy Ƀ0.26219275 at a rate of 0.0026272 with US$ 0.20 commission. + +To represent the sale of Bitcoins use `CEXSell` like this: + +```swift +CEXSell.quote(50) { result in + if let tx = result.value { + print("\(tx.base) will sell for \(tx.counter) at a rate of \(tx.rate) with \(tx.commission) commission.") + } +} +``` +> Ƀ50.00 will sell for € 17,541.87 at a rate of 351.5405 with Ƀ0.10 commission. + +If trying to buy or sell using a currency not supported by CEX the compiler will prevent your code from compiling. + +```swift +CEXSell.quote(50) { result in + // etc +} +``` +> Type 'Currency.GBP' does not conform to protocol 'CEXSupportedFiatCurrencyType' # Creating custom currencies diff --git a/Supporting Files/Money.xcconfig b/Supporting Files/Money.xcconfig index 1d3979c..da46098 100644 --- a/Supporting Files/Money.xcconfig +++ b/Supporting Files/Money.xcconfig @@ -6,7 +6,7 @@ // // -MONEY_VERSION = 1.1.0 +MONEY_VERSION = 1.2.0 APPLICATION_EXTENSION_API_ONLY = YES INFOPLIST_FILE = $(SRCROOT)/Supporting Files/Info.plist diff --git a/Tests/BitcoinTests.swift b/Tests/BitcoinTests.swift new file mode 100644 index 0000000..60324f0 --- /dev/null +++ b/Tests/BitcoinTests.swift @@ -0,0 +1,215 @@ +// +// BitcoinTests.swift +// Money +// +// Created by Daniel Thorpe on 08/11/2015. +// +// + +import XCTest +import Result +import DVR +import SwiftyJSON +@testable import Money + + +class BitcoinCurrencyTests: XCTestCase { + + func test__xbt_currency_code() { + XCTAssertEqual(Currency.XBT.code, "XBT") + } + + func test__btc_currency_code() { + XCTAssertEqual(Currency.BTC.code, "BTC") + } + + func test__btc_currency_symbol() { + XCTAssertEqual(Currency.BTC.symbol, "Ƀ") + } + + func test__btc_currency_scale() { + XCTAssertEqual(Currency.BTC.scale, 8) + } +} + +class CEXTests: XCTestCase { + + func test__usd_commission_percentage() { + XCTAssertEqual(Currency.USD.cex_commissionPercentage, 0.2) + } + + func test__eur_commission_percentage() { + XCTAssertEqual(Currency.EUR.cex_commissionPercentage, 0.2) + } + + func test__rub_commission_percentage() { + XCTAssertEqual(Currency.RUB.cex_commissionPercentage, 0) + } +} + +class FXCEXBuyTests: FXProviderTests { + + typealias Provider = CEXBuy + typealias TestableProvider = TestableFXRemoteProvider + typealias FaultyProvider = FaultyFXRemoteProvider + + func test__name() { + XCTAssertEqual(Provider.name(), "CEX.IO USDBTC") + } + + func test__session() { + XCTAssertEqual(Provider.session(), NSURLSession.sharedSession()) + } + + func test__quote_adaptor__with_network_error() { + let error = NSError(domain: NSURLErrorDomain, code: NSURLError.BadServerResponse.rawValue, userInfo: nil) + let network: Result<(NSData?, NSURLResponse?), NSError> = Result(error: error) + let quote = Provider.quoteFromNetworkResult(network) + XCTAssertEqual(quote.error!, FXError.NetworkError(error)) + } + + func test__quote_adaptor__with_no_data() { + let network: Result<(NSData?, NSURLResponse?), NSError> = Result(value: (.None, .None)) + let quote = Provider.quoteFromNetworkResult(network) + XCTAssertEqual(quote.error!, FXError.NoData) + } + + func test__quote_adaptor__with_garbage_data() { + let data = createGarbageData() + let network: Result<(NSData?, NSURLResponse?), NSError> = Result(value: (data, .None)) + let quote = Provider.quoteFromNetworkResult(network) + XCTAssertEqual(quote.error!, FXError.InvalidData(data)) + } + + func test__quote_adaptor__with_missing_rate() { + let json = dvrJSONFromCassette(Provider.name())! + var dic = json.dictionaryValue + dic["amount"] = json["amnt"] + dic.removeValueForKey("amnt") + let data = try! JSON(dic).rawData() + let network: Result<(NSData?, NSURLResponse?), NSError> = Result(value: (data, .None)) + let quote = Provider.quoteFromNetworkResult(network) + XCTAssertEqual(quote.error!, FXError.RateNotFound(Provider.name())) + } + + func test__faulty_provider() { + let expectation = expectationWithDescription("Test: \(__FUNCTION__)") + + FaultyProvider.fx(100) { result in + guard let error = result.error else { + XCTFail("Should have received a network error.") + return + } + switch error { + case .NetworkError(_): + break // This is the success path. + default: + XCTFail("Returned \(error), should be a .NetworkError") + } + expectation.fulfill() + } + + waitForExpectationsWithTimeout(1, handler: nil) + } + + func test__fx() { + let expectation = expectationWithDescription("Test: \(__FUNCTION__)") + + TestableProvider.fx(100) { result in + if let usd = result.value { + XCTAssertEqual(usd, 0.25470294) + } + else { + XCTFail("Received error: \(result.error!).") + } + expectation.fulfill() + } + + waitForExpectationsWithTimeout(1, handler: nil) + } + +} + +class FXCEXSellTests: FXProviderTests { + + typealias Provider = CEXSell + typealias TestableProvider = TestableFXRemoteProvider + typealias FaultyProvider = FaultyFXRemoteProvider + + func test__name() { + XCTAssertEqual(Provider.name(), "CEX.IO BTCUSD") + } + + func test__session() { + XCTAssertEqual(Provider.session(), NSURLSession.sharedSession()) + } + + func test__quote_adaptor__with_network_error() { + let error = NSError(domain: NSURLErrorDomain, code: NSURLError.BadServerResponse.rawValue, userInfo: nil) + let network: Result<(NSData?, NSURLResponse?), NSError> = Result(error: error) + let quote = Provider.quoteFromNetworkResult(network) + XCTAssertEqual(quote.error!, FXError.NetworkError(error)) + } + + func test__quote_adaptor__with_no_data() { + let network: Result<(NSData?, NSURLResponse?), NSError> = Result(value: (.None, .None)) + let quote = Provider.quoteFromNetworkResult(network) + XCTAssertEqual(quote.error!, FXError.NoData) + } + + func test__quote_adaptor__with_garbage_data() { + let data = createGarbageData() + let network: Result<(NSData?, NSURLResponse?), NSError> = Result(value: (data, .None)) + let quote = Provider.quoteFromNetworkResult(network) + XCTAssertEqual(quote.error!, FXError.InvalidData(data)) + } + + func test__quote_adaptor__with_missing_rate() { + let json = dvrJSONFromCassette(Provider.name())! + var dic = json.dictionaryValue + dic["amount"] = json["amnt"] + dic.removeValueForKey("amnt") + let data = try! JSON(dic).rawData() + let network: Result<(NSData?, NSURLResponse?), NSError> = Result(value: (data, .None)) + let quote = Provider.quoteFromNetworkResult(network) + XCTAssertEqual(quote.error!, FXError.RateNotFound(Provider.name())) + } + + func test__faulty_provider() { + let expectation = expectationWithDescription("Test: \(__FUNCTION__)") + + FaultyProvider.fx(100) { result in + guard let error = result.error else { + XCTFail("Should have received a network error.") + return + } + switch error { + case .NetworkError(_): + break // This is the success path. + default: + XCTFail("Returned \(error), should be a .NetworkError") + } + expectation.fulfill() + } + + waitForExpectationsWithTimeout(1, handler: nil) + } + + func test__fx() { + let expectation = expectationWithDescription("Test: \(__FUNCTION__)") + + TestableProvider.fx(100) { result in + if let btc = result.value { + XCTAssertEqual(btc, 39_198.35) + } + else { + XCTFail("Received error: \(result.error!).") + } + expectation.fulfill() + } + + waitForExpectationsWithTimeout(1, handler: nil) +} + +} + diff --git a/Tests/DVR Cassettes/CEX.IO BTCUSD.json b/Tests/DVR Cassettes/CEX.IO BTCUSD.json new file mode 100644 index 0000000..a21a649 --- /dev/null +++ b/Tests/DVR Cassettes/CEX.IO BTCUSD.json @@ -0,0 +1,33 @@ +{ + "interactions" : [ + { + "recorded_at" : 1447005471.048528, + "response" : { + "body" : "{\"amnt\":392.769}", + "status" : 200, + "url" : "https:\/\/cex.io\/api\/convert\/BTC\/USD", + "headers" : { + "cf-ray" : "242329a0c16434fa-LHR", + "Content-Type" : "text\/json", + "Server" : "cloudflare-nginx", + "Set-Cookie" : "__cfduid=d8814e674eaa6d74dc7111b40e1725e7b1447005470; expires=Mon, 07-Nov-16 17:57:50 GMT; path=\/; domain=.cex.io; HttpOnly, cex-prod-session=s%3A6IA4GuKmoXs-ScYlPBKxws7x.uy4t0GEq2h32KeFJtxSJqirGgP6s44E%2FLaOe%2FhN%2F4x0; Domain=.cex.io; Path=\/; HttpOnly; Secure", + "Vary" : "Accept-Encoding", + "Date" : "Sun, 08 Nov 2015 17:57:50 GMT", + "x-frame-options" : "DENY", + "Access-Control-Allow-Origin" : "*" + } + }, + "request" : { + "method" : "POST", + "body" : { + "amnt" : 1 + }, + "url" : "https:\/\/cex.io\/api\/convert\/BTC\/USD", + "headers" : { + "Content-Type" : "application\/json" + } + } + } + ], + "name" : "CEX.IO BTCUSD" +} diff --git a/Tests/DVR Cassettes/CEX.IO USDBTC.json b/Tests/DVR Cassettes/CEX.IO USDBTC.json new file mode 100644 index 0000000..53fdbe8 --- /dev/null +++ b/Tests/DVR Cassettes/CEX.IO USDBTC.json @@ -0,0 +1,33 @@ +{ + "interactions" : [ + { + "recorded_at" : 1447008110.14736, + "response" : { + "body" : "{\"amnt\":391.829}", + "status" : 200, + "url" : "https:\/\/cex.io\/api\/convert\/BTC\/USD", + "headers" : { + "cf-ray" : "24236a1032de359c-LHR", + "Content-Type" : "text\/json", + "Server" : "cloudflare-nginx", + "Set-Cookie" : "__cfduid=d0c2769b88e78f6e46f6c4c5fccb84c081447008110; expires=Mon, 07-Nov-16 18:41:50 GMT; path=\/; domain=.cex.io; HttpOnly, cex-prod-session=s%3AvnzWUOJ65E4m9XYY5vh_JvmJ.LwHdvFj55w6G%2Bxo1jkzIyyE6n0dY%2FiC6GXiqK4tlQgk; Domain=.cex.io; Path=\/; HttpOnly; Secure", + "Vary" : "Accept-Encoding", + "Date" : "Sun, 08 Nov 2015 18:41:50 GMT", + "x-frame-options" : "DENY", + "Access-Control-Allow-Origin" : "*" + } + }, + "request" : { + "method" : "POST", + "body" : { + "amnt" : 1 + }, + "url" : "https:\/\/cex.io\/api\/convert\/BTC\/USD", + "headers" : { + "Content-Type" : "application\/json" + } + } + } + ], + "name" : "CEX.IO USDBTC" +} diff --git a/Tests/FXTests.swift b/Tests/FXTests.swift index 12ddfb1..c32f39e 100644 --- a/Tests/FXTests.swift +++ b/Tests/FXTests.swift @@ -84,7 +84,11 @@ class FaultyFXRemoteProvider: FXRemoteProviderTy class FakeLocalFX: FXLocalProviderType { typealias BaseMoney = B @@ -123,9 +127,7 @@ class FXProviderTests: XCTestCase { class FXLocalProviderTests: XCTestCase { func test_fx() { - let money: Money = 10 - let usd: USD = FakeLocalFX.fx(money) - XCTAssertEqual(usd, 11) + XCTAssertEqual(FakeLocalFX.fx(100).counter, 110) } } @@ -134,11 +136,11 @@ class FXQuoteTests: XCTestCase { var quote: FXQuote! func archiveEncodedQuote() -> NSData { - return NSKeyedArchiver.archivedDataWithRootObject(quote) + return NSKeyedArchiver.archivedDataWithRootObject(quote.encoded) } func unarchive(archive: NSData) -> FXQuote? { - return NSKeyedUnarchiver.unarchiveObjectWithData(archive) as? FXQuote + return FXQuote.decode(NSKeyedUnarchiver.unarchiveObjectWithData(archive)) } func test__quote_encodes() { @@ -146,3 +148,23 @@ class FXQuoteTests: XCTestCase { XCTAssertEqual(unarchive(archiveEncodedQuote())!.rate, quote.rate) } } + +class FXTransactionTests: XCTestCase { + + typealias Transaction = FXTransaction + + var transaction: Transaction! + + func archiveEncodedTransaction() -> NSData { + return NSKeyedArchiver.archivedDataWithRootObject(transaction.encoded) + } + + func unarchive(archive: NSData) -> Transaction? { + return Transaction.decode(NSKeyedUnarchiver.unarchiveObjectWithData(archive)) + } + + func test__transaction_encodes() { + transaction = Transaction(base: 100, quote: FXQuote(rate: 1.2)) + XCTAssertEqual(unarchive(archiveEncodedTransaction())!.base, 100) + } +}