├── .gitignore ├── .swift-version ├── CryptoCurrencyKit.podspec ├── CryptoCurrencyKit.xcodeproj ├── CryptoCurrencyKitTests_Info.plist ├── CryptoCurrencyKit_Info.plist ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ ├── CryptoCurrencyKit.xcscheme │ └── xcschememanagement.plist ├── Demo └── main.swift ├── LICENSE ├── Package.swift ├── README.md └── Sources ├── CryptoCurrencyKit.swift ├── Global.swift ├── Graph.swift ├── Request.swift └── Ticker.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | .build/ 8 | /Packages 9 | .DS_Store 10 | DerivedData/ 11 | 12 | ## Various settings 13 | *.pbxuser 14 | !default.pbxuser 15 | *.mode1v3 16 | !default.mode1v3 17 | *.mode2v3 18 | !default.mode2v3 19 | *.perspectivev3 20 | !default.perspectivev3 21 | xcuserdata/ 22 | 23 | ## Other 24 | *.moved-aside 25 | *.xccheckout 26 | *.xcscmblueprint 27 | 28 | ## Obj-C/Swift specific 29 | *.hmap 30 | *.ipa 31 | *.dSYM.zip 32 | *.dSYM 33 | 34 | # CocoaPods 35 | # 36 | # We recommend against adding the Pods directory to your .gitignore. However 37 | # you should judge for yourself, the pros and cons are mentioned at: 38 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 39 | # 40 | Pods/ 41 | 42 | # Carthage 43 | # 44 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 45 | Carthage/Checkouts 46 | Carthage/Build 47 | 48 | # fastlane 49 | # 50 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 51 | # screenshots whenever they are needed. 52 | # For more information about the recommended setup visit: 53 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 54 | 55 | fastlane/report.xml 56 | fastlane/Preview.html 57 | fastlane/screenshots 58 | fastlane/test_output 59 | 60 | # Code Injection 61 | # 62 | # After new code Injection tools there's a generated folder /iOSInjectionProject 63 | # https://github.com/johnno1962/injectionforxcode 64 | 65 | iOSInjectionProject/ -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.0 2 | -------------------------------------------------------------------------------- /CryptoCurrencyKit.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'CryptoCurrencyKit' 3 | s.version = '0.3.1' 4 | s.license = { :type => "MIT", :file => "LICENSE" } 5 | s.homepage = 'https://github.com/iCell/CryptoCurrency' 6 | s.authors = { 'iCell' => 'icell.vip@gmail.com' } 7 | s.summary = 'A Swift crypto-currencies price library for accessing coinmarket APIs.' 8 | 9 | s.source = { :git => 'https://github.com/iCell/CryptoCurrency.git', :tag => s.version } 10 | 11 | s.ios.deployment_target = '8.0' 12 | s.osx.deployment_target = '10.10' 13 | 14 | s.source_files = 'Sources/*.swift' 15 | s.framework = 'Foundation' 16 | end -------------------------------------------------------------------------------- /CryptoCurrencyKit.xcodeproj/CryptoCurrencyKitTests_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | BNDL 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /CryptoCurrencyKit.xcodeproj/CryptoCurrencyKit_Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | CFBundleDevelopmentRegion 5 | en 6 | CFBundleExecutable 7 | $(EXECUTABLE_NAME) 8 | CFBundleIdentifier 9 | $(PRODUCT_BUNDLE_IDENTIFIER) 10 | CFBundleInfoDictionaryVersion 11 | 6.0 12 | CFBundleName 13 | $(PRODUCT_NAME) 14 | CFBundlePackageType 15 | FMWK 16 | CFBundleShortVersionString 17 | 1.0 18 | CFBundleSignature 19 | ???? 20 | CFBundleVersion 21 | $(CURRENT_PROJECT_VERSION) 22 | NSPrincipalClass 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /CryptoCurrencyKit.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E81D561B1F720B9800EDBDBB /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E81D561A1F720B9800EDBDBB /* main.swift */; }; 11 | E8D027421F7F4E9500C0F33A /* Request.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D027411F7F4E9500C0F33A /* Request.swift */; }; 12 | E8D027441F7F598E00C0F33A /* Graph.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8D027431F7F598E00C0F33A /* Graph.swift */; }; 13 | OBJ_21 /* Package.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_6 /* Package.swift */; }; 14 | OBJ_27 /* CryptoCurrencyKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_10 /* CryptoCurrencyKit.swift */; }; 15 | OBJ_28 /* Global.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_11 /* Global.swift */; }; 16 | OBJ_29 /* Ticker.swift in Sources */ = {isa = PBXBuildFile; fileRef = OBJ_12 /* Ticker.swift */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXContainerItemProxy section */ 20 | E81D561F1F720BA000EDBDBB /* PBXContainerItemProxy */ = { 21 | isa = PBXContainerItemProxy; 22 | containerPortal = OBJ_1 /* Project object */; 23 | proxyType = 1; 24 | remoteGlobalIDString = "CryptoCurrencyKit::CryptoCurrencyKit"; 25 | remoteInfo = CryptoCurrencyKit; 26 | }; 27 | /* End PBXContainerItemProxy section */ 28 | 29 | /* Begin PBXCopyFilesBuildPhase section */ 30 | E81D56161F720B9800EDBDBB /* CopyFiles */ = { 31 | isa = PBXCopyFilesBuildPhase; 32 | buildActionMask = 2147483647; 33 | dstPath = /usr/share/man/man1/; 34 | dstSubfolderSpec = 0; 35 | files = ( 36 | ); 37 | runOnlyForDeploymentPostprocessing = 1; 38 | }; 39 | /* End PBXCopyFilesBuildPhase section */ 40 | 41 | /* Begin PBXFileReference section */ 42 | "CryptoCurrencyKit::CryptoCurrencyKit::Product" /* CryptoCurrencyKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = CryptoCurrencyKit.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 43 | E81D56181F720B9800EDBDBB /* Demo */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Demo; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | E81D561A1F720B9800EDBDBB /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 45 | E8D027411F7F4E9500C0F33A /* Request.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Request.swift; sourceTree = ""; }; 46 | E8D027431F7F598E00C0F33A /* Graph.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Graph.swift; sourceTree = ""; }; 47 | OBJ_10 /* CryptoCurrencyKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CryptoCurrencyKit.swift; sourceTree = ""; }; 48 | OBJ_11 /* Global.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Global.swift; sourceTree = ""; }; 49 | OBJ_12 /* Ticker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Ticker.swift; sourceTree = ""; }; 50 | OBJ_6 /* Package.swift */ = {isa = PBXFileReference; explicitFileType = sourcecode.swift; path = Package.swift; sourceTree = ""; }; 51 | /* End PBXFileReference section */ 52 | 53 | /* Begin PBXFrameworksBuildPhase section */ 54 | E81D56151F720B9800EDBDBB /* Frameworks */ = { 55 | isa = PBXFrameworksBuildPhase; 56 | buildActionMask = 2147483647; 57 | files = ( 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | OBJ_30 /* Frameworks */ = { 62 | isa = PBXFrameworksBuildPhase; 63 | buildActionMask = 0; 64 | files = ( 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | /* End PBXFrameworksBuildPhase section */ 69 | 70 | /* Begin PBXGroup section */ 71 | E81D56191F720B9800EDBDBB /* Demo */ = { 72 | isa = PBXGroup; 73 | children = ( 74 | E81D561A1F720B9800EDBDBB /* main.swift */, 75 | ); 76 | path = Demo; 77 | sourceTree = ""; 78 | }; 79 | OBJ_13 /* Tests */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | ); 83 | name = Tests; 84 | sourceTree = SOURCE_ROOT; 85 | }; 86 | OBJ_14 /* Products */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | "CryptoCurrencyKit::CryptoCurrencyKit::Product" /* CryptoCurrencyKit.framework */, 90 | E81D56181F720B9800EDBDBB /* Demo */, 91 | ); 92 | name = Products; 93 | sourceTree = BUILT_PRODUCTS_DIR; 94 | }; 95 | OBJ_5 = { 96 | isa = PBXGroup; 97 | children = ( 98 | OBJ_6 /* Package.swift */, 99 | OBJ_7 /* Sources */, 100 | OBJ_13 /* Tests */, 101 | E81D56191F720B9800EDBDBB /* Demo */, 102 | OBJ_14 /* Products */, 103 | ); 104 | sourceTree = ""; 105 | }; 106 | OBJ_7 /* Sources */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | OBJ_8 /* CryptoCurrencyKit */, 110 | ); 111 | name = Sources; 112 | sourceTree = SOURCE_ROOT; 113 | }; 114 | OBJ_8 /* CryptoCurrencyKit */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | OBJ_9 /* Sources */, 118 | ); 119 | name = CryptoCurrencyKit; 120 | sourceTree = SOURCE_ROOT; 121 | }; 122 | OBJ_9 /* Sources */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | OBJ_10 /* CryptoCurrencyKit.swift */, 126 | E8D027411F7F4E9500C0F33A /* Request.swift */, 127 | OBJ_11 /* Global.swift */, 128 | OBJ_12 /* Ticker.swift */, 129 | E8D027431F7F598E00C0F33A /* Graph.swift */, 130 | ); 131 | path = Sources; 132 | sourceTree = ""; 133 | }; 134 | /* End PBXGroup section */ 135 | 136 | /* Begin PBXNativeTarget section */ 137 | "CryptoCurrencyKit::CryptoCurrencyKit" /* CryptoCurrencyKit */ = { 138 | isa = PBXNativeTarget; 139 | buildConfigurationList = OBJ_23 /* Build configuration list for PBXNativeTarget "CryptoCurrencyKit" */; 140 | buildPhases = ( 141 | OBJ_26 /* Sources */, 142 | OBJ_30 /* Frameworks */, 143 | ); 144 | buildRules = ( 145 | ); 146 | dependencies = ( 147 | ); 148 | name = CryptoCurrencyKit; 149 | productName = CryptoCurrencyKit; 150 | productReference = "CryptoCurrencyKit::CryptoCurrencyKit::Product" /* CryptoCurrencyKit.framework */; 151 | productType = "com.apple.product-type.framework"; 152 | }; 153 | "CryptoCurrencyKit::SwiftPMPackageDescription" /* CryptoCurrencyKitPackageDescription */ = { 154 | isa = PBXNativeTarget; 155 | buildConfigurationList = OBJ_17 /* Build configuration list for PBXNativeTarget "CryptoCurrencyKitPackageDescription" */; 156 | buildPhases = ( 157 | OBJ_20 /* Sources */, 158 | ); 159 | buildRules = ( 160 | ); 161 | dependencies = ( 162 | ); 163 | name = CryptoCurrencyKitPackageDescription; 164 | productName = CryptoCurrencyKitPackageDescription; 165 | productType = "com.apple.product-type.framework"; 166 | }; 167 | E81D56171F720B9800EDBDBB /* Demo */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = E81D561E1F720B9800EDBDBB /* Build configuration list for PBXNativeTarget "Demo" */; 170 | buildPhases = ( 171 | E81D56141F720B9800EDBDBB /* Sources */, 172 | E81D56151F720B9800EDBDBB /* Frameworks */, 173 | E81D56161F720B9800EDBDBB /* CopyFiles */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | E81D56201F720BA000EDBDBB /* PBXTargetDependency */, 179 | ); 180 | name = Demo; 181 | productName = Demo; 182 | productReference = E81D56181F720B9800EDBDBB /* Demo */; 183 | productType = "com.apple.product-type.tool"; 184 | }; 185 | /* End PBXNativeTarget section */ 186 | 187 | /* Begin PBXProject section */ 188 | OBJ_1 /* Project object */ = { 189 | isa = PBXProject; 190 | attributes = { 191 | LastSwiftUpdateCheck = 0900; 192 | LastUpgradeCheck = 9999; 193 | TargetAttributes = { 194 | E81D56171F720B9800EDBDBB = { 195 | CreatedOnToolsVersion = 9.0; 196 | ProvisioningStyle = Automatic; 197 | }; 198 | }; 199 | }; 200 | buildConfigurationList = OBJ_2 /* Build configuration list for PBXProject "CryptoCurrencyKit" */; 201 | compatibilityVersion = "Xcode 3.2"; 202 | developmentRegion = English; 203 | hasScannedForEncodings = 0; 204 | knownRegions = ( 205 | en, 206 | ); 207 | mainGroup = OBJ_5; 208 | productRefGroup = OBJ_14 /* Products */; 209 | projectDirPath = ""; 210 | projectRoot = ""; 211 | targets = ( 212 | "CryptoCurrencyKit::SwiftPMPackageDescription" /* CryptoCurrencyKitPackageDescription */, 213 | "CryptoCurrencyKit::CryptoCurrencyKit" /* CryptoCurrencyKit */, 214 | E81D56171F720B9800EDBDBB /* Demo */, 215 | ); 216 | }; 217 | /* End PBXProject section */ 218 | 219 | /* Begin PBXSourcesBuildPhase section */ 220 | E81D56141F720B9800EDBDBB /* Sources */ = { 221 | isa = PBXSourcesBuildPhase; 222 | buildActionMask = 2147483647; 223 | files = ( 224 | E81D561B1F720B9800EDBDBB /* main.swift in Sources */, 225 | ); 226 | runOnlyForDeploymentPostprocessing = 0; 227 | }; 228 | OBJ_20 /* Sources */ = { 229 | isa = PBXSourcesBuildPhase; 230 | buildActionMask = 0; 231 | files = ( 232 | OBJ_21 /* Package.swift in Sources */, 233 | ); 234 | runOnlyForDeploymentPostprocessing = 0; 235 | }; 236 | OBJ_26 /* Sources */ = { 237 | isa = PBXSourcesBuildPhase; 238 | buildActionMask = 0; 239 | files = ( 240 | OBJ_27 /* CryptoCurrencyKit.swift in Sources */, 241 | E8D027421F7F4E9500C0F33A /* Request.swift in Sources */, 242 | OBJ_28 /* Global.swift in Sources */, 243 | OBJ_29 /* Ticker.swift in Sources */, 244 | E8D027441F7F598E00C0F33A /* Graph.swift in Sources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | /* End PBXSourcesBuildPhase section */ 249 | 250 | /* Begin PBXTargetDependency section */ 251 | E81D56201F720BA000EDBDBB /* PBXTargetDependency */ = { 252 | isa = PBXTargetDependency; 253 | target = "CryptoCurrencyKit::CryptoCurrencyKit" /* CryptoCurrencyKit */; 254 | targetProxy = E81D561F1F720BA000EDBDBB /* PBXContainerItemProxy */; 255 | }; 256 | /* End PBXTargetDependency section */ 257 | 258 | /* Begin XCBuildConfiguration section */ 259 | E81D561C1F720B9800EDBDBB /* Debug */ = { 260 | isa = XCBuildConfiguration; 261 | buildSettings = { 262 | ALWAYS_SEARCH_USER_PATHS = NO; 263 | CLANG_ANALYZER_NONNULL = YES; 264 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 265 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 266 | CLANG_CXX_LIBRARY = "libc++"; 267 | CLANG_ENABLE_MODULES = YES; 268 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 269 | CLANG_WARN_BOOL_CONVERSION = YES; 270 | CLANG_WARN_COMMA = YES; 271 | CLANG_WARN_CONSTANT_CONVERSION = YES; 272 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 273 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 274 | CLANG_WARN_EMPTY_BODY = YES; 275 | CLANG_WARN_ENUM_CONVERSION = YES; 276 | CLANG_WARN_INFINITE_RECURSION = YES; 277 | CLANG_WARN_INT_CONVERSION = YES; 278 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 279 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 280 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 281 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 282 | CLANG_WARN_STRICT_PROTOTYPES = YES; 283 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 284 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 285 | CLANG_WARN_UNREACHABLE_CODE = YES; 286 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 287 | CODE_SIGN_IDENTITY = "-"; 288 | CODE_SIGN_STYLE = Automatic; 289 | ENABLE_STRICT_OBJC_MSGSEND = YES; 290 | ENABLE_TESTABILITY = YES; 291 | GCC_C_LANGUAGE_STANDARD = gnu11; 292 | GCC_DYNAMIC_NO_PIC = NO; 293 | GCC_NO_COMMON_BLOCKS = YES; 294 | GCC_PREPROCESSOR_DEFINITIONS = ( 295 | "DEBUG=1", 296 | "$(inherited)", 297 | ); 298 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 299 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 300 | GCC_WARN_UNDECLARED_SELECTOR = YES; 301 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 302 | GCC_WARN_UNUSED_FUNCTION = YES; 303 | GCC_WARN_UNUSED_VARIABLE = YES; 304 | MACOSX_DEPLOYMENT_TARGET = 10.12; 305 | MTL_ENABLE_DEBUG_INFO = YES; 306 | PRODUCT_NAME = "$(TARGET_NAME)"; 307 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 308 | SWIFT_VERSION = 4.0; 309 | }; 310 | name = Debug; 311 | }; 312 | E81D561D1F720B9800EDBDBB /* Release */ = { 313 | isa = XCBuildConfiguration; 314 | buildSettings = { 315 | ALWAYS_SEARCH_USER_PATHS = NO; 316 | CLANG_ANALYZER_NONNULL = YES; 317 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 318 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 319 | CLANG_CXX_LIBRARY = "libc++"; 320 | CLANG_ENABLE_MODULES = YES; 321 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 322 | CLANG_WARN_BOOL_CONVERSION = YES; 323 | CLANG_WARN_COMMA = YES; 324 | CLANG_WARN_CONSTANT_CONVERSION = YES; 325 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 326 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 327 | CLANG_WARN_EMPTY_BODY = YES; 328 | CLANG_WARN_ENUM_CONVERSION = YES; 329 | CLANG_WARN_INFINITE_RECURSION = YES; 330 | CLANG_WARN_INT_CONVERSION = YES; 331 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 332 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 333 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 334 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 335 | CLANG_WARN_STRICT_PROTOTYPES = YES; 336 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 337 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 338 | CLANG_WARN_UNREACHABLE_CODE = YES; 339 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 340 | CODE_SIGN_IDENTITY = "-"; 341 | CODE_SIGN_STYLE = Automatic; 342 | COPY_PHASE_STRIP = NO; 343 | ENABLE_NS_ASSERTIONS = NO; 344 | ENABLE_STRICT_OBJC_MSGSEND = YES; 345 | GCC_C_LANGUAGE_STANDARD = gnu11; 346 | GCC_NO_COMMON_BLOCKS = YES; 347 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 348 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 349 | GCC_WARN_UNDECLARED_SELECTOR = YES; 350 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 351 | GCC_WARN_UNUSED_FUNCTION = YES; 352 | GCC_WARN_UNUSED_VARIABLE = YES; 353 | MACOSX_DEPLOYMENT_TARGET = 10.12; 354 | MTL_ENABLE_DEBUG_INFO = NO; 355 | PRODUCT_NAME = "$(TARGET_NAME)"; 356 | SWIFT_VERSION = 4.0; 357 | }; 358 | name = Release; 359 | }; 360 | OBJ_18 /* Debug */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | LD = /usr/bin/true; 364 | OTHER_SWIFT_FLAGS = "-swift-version 4 -I /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/4 -target x86_64-apple-macosx10.10 -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk"; 365 | SWIFT_VERSION = 4.0; 366 | }; 367 | name = Debug; 368 | }; 369 | OBJ_19 /* Release */ = { 370 | isa = XCBuildConfiguration; 371 | buildSettings = { 372 | LD = /usr/bin/true; 373 | OTHER_SWIFT_FLAGS = "-swift-version 4 -I /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/pm/4 -target x86_64-apple-macosx10.10 -sdk /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk"; 374 | SWIFT_VERSION = 4.0; 375 | }; 376 | name = Release; 377 | }; 378 | OBJ_24 /* Debug */ = { 379 | isa = XCBuildConfiguration; 380 | buildSettings = { 381 | ENABLE_TESTABILITY = YES; 382 | FRAMEWORK_SEARCH_PATHS = ( 383 | "$(inherited)", 384 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 385 | ); 386 | HEADER_SEARCH_PATHS = "$(inherited)"; 387 | INFOPLIST_FILE = CryptoCurrencyKit.xcodeproj/CryptoCurrencyKit_Info.plist; 388 | LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 389 | OTHER_LDFLAGS = "$(inherited)"; 390 | OTHER_SWIFT_FLAGS = "$(inherited)"; 391 | PRODUCT_BUNDLE_IDENTIFIER = CryptoCurrencyKit; 392 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 393 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 394 | SKIP_INSTALL = YES; 395 | SWIFT_VERSION = 4.0; 396 | TARGET_NAME = CryptoCurrencyKit; 397 | }; 398 | name = Debug; 399 | }; 400 | OBJ_25 /* Release */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | ENABLE_TESTABILITY = YES; 404 | FRAMEWORK_SEARCH_PATHS = ( 405 | "$(inherited)", 406 | "$(PLATFORM_DIR)/Developer/Library/Frameworks", 407 | ); 408 | HEADER_SEARCH_PATHS = "$(inherited)"; 409 | INFOPLIST_FILE = CryptoCurrencyKit.xcodeproj/CryptoCurrencyKit_Info.plist; 410 | LD_RUNPATH_SEARCH_PATHS = "$(TOOLCHAIN_DIR)/usr/lib/swift/macosx"; 411 | OTHER_LDFLAGS = "$(inherited)"; 412 | OTHER_SWIFT_FLAGS = "$(inherited)"; 413 | PRODUCT_BUNDLE_IDENTIFIER = CryptoCurrencyKit; 414 | PRODUCT_MODULE_NAME = "$(TARGET_NAME:c99extidentifier)"; 415 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 416 | SKIP_INSTALL = YES; 417 | SWIFT_VERSION = 4.0; 418 | TARGET_NAME = CryptoCurrencyKit; 419 | }; 420 | name = Release; 421 | }; 422 | OBJ_3 /* Debug */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | CLANG_ENABLE_OBJC_ARC = YES; 426 | COMBINE_HIDPI_IMAGES = YES; 427 | COPY_PHASE_STRIP = NO; 428 | DEBUG_INFORMATION_FORMAT = dwarf; 429 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 430 | ENABLE_NS_ASSERTIONS = YES; 431 | GCC_OPTIMIZATION_LEVEL = 0; 432 | MACOSX_DEPLOYMENT_TARGET = 10.10; 433 | ONLY_ACTIVE_ARCH = YES; 434 | OTHER_SWIFT_FLAGS = "-DXcode"; 435 | PRODUCT_NAME = "$(TARGET_NAME)"; 436 | SDKROOT = macosx; 437 | SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; 438 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; 439 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 440 | USE_HEADERMAP = NO; 441 | }; 442 | name = Debug; 443 | }; 444 | OBJ_4 /* Release */ = { 445 | isa = XCBuildConfiguration; 446 | buildSettings = { 447 | CLANG_ENABLE_OBJC_ARC = YES; 448 | COMBINE_HIDPI_IMAGES = YES; 449 | COPY_PHASE_STRIP = YES; 450 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 451 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 452 | GCC_OPTIMIZATION_LEVEL = s; 453 | MACOSX_DEPLOYMENT_TARGET = 10.10; 454 | OTHER_SWIFT_FLAGS = "-DXcode"; 455 | PRODUCT_NAME = "$(TARGET_NAME)"; 456 | SDKROOT = macosx; 457 | SUPPORTED_PLATFORMS = "macosx iphoneos iphonesimulator appletvos appletvsimulator watchos watchsimulator"; 458 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = SWIFT_PACKAGE; 459 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 460 | USE_HEADERMAP = NO; 461 | }; 462 | name = Release; 463 | }; 464 | /* End XCBuildConfiguration section */ 465 | 466 | /* Begin XCConfigurationList section */ 467 | E81D561E1F720B9800EDBDBB /* Build configuration list for PBXNativeTarget "Demo" */ = { 468 | isa = XCConfigurationList; 469 | buildConfigurations = ( 470 | E81D561C1F720B9800EDBDBB /* Debug */, 471 | E81D561D1F720B9800EDBDBB /* Release */, 472 | ); 473 | defaultConfigurationIsVisible = 0; 474 | defaultConfigurationName = Debug; 475 | }; 476 | OBJ_17 /* Build configuration list for PBXNativeTarget "CryptoCurrencyKitPackageDescription" */ = { 477 | isa = XCConfigurationList; 478 | buildConfigurations = ( 479 | OBJ_18 /* Debug */, 480 | OBJ_19 /* Release */, 481 | ); 482 | defaultConfigurationIsVisible = 0; 483 | defaultConfigurationName = Debug; 484 | }; 485 | OBJ_2 /* Build configuration list for PBXProject "CryptoCurrencyKit" */ = { 486 | isa = XCConfigurationList; 487 | buildConfigurations = ( 488 | OBJ_3 /* Debug */, 489 | OBJ_4 /* Release */, 490 | ); 491 | defaultConfigurationIsVisible = 0; 492 | defaultConfigurationName = Debug; 493 | }; 494 | OBJ_23 /* Build configuration list for PBXNativeTarget "CryptoCurrencyKit" */ = { 495 | isa = XCConfigurationList; 496 | buildConfigurations = ( 497 | OBJ_24 /* Debug */, 498 | OBJ_25 /* Release */, 499 | ); 500 | defaultConfigurationIsVisible = 0; 501 | defaultConfigurationName = Debug; 502 | }; 503 | /* End XCConfigurationList section */ 504 | }; 505 | rootObject = OBJ_1 /* Project object */; 506 | } 507 | -------------------------------------------------------------------------------- /CryptoCurrencyKit.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CryptoCurrencyKit.xcodeproj/xcshareddata/xcschemes/CryptoCurrencyKit.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 72 | 73 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /CryptoCurrencyKit.xcodeproj/xcshareddata/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | SchemeUserState 5 | 6 | CryptoCurrencyKit-Package.xcscheme 7 | 8 | 9 | SuppressBuildableAutocreation 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Demo/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // Demo 4 | // 5 | // Created by Xiaoyu Li on 20/09/2017. 6 | // 7 | 8 | import Foundation 9 | import CryptoCurrencyKit 10 | 11 | func fetchTickers() { 12 | CryptoCurrencyKit.fetchTickers { r in 13 | switch r { 14 | case .success(let tickers): 15 | print(tickers) 16 | case .failure(let error): 17 | print(error) 18 | } 19 | } 20 | } 21 | 22 | func fetchBitcoin() { 23 | CryptoCurrencyKit.fetchTicker(coinName: "BitCoin", convert: .jpy) { r in 24 | switch r { 25 | case .success(let bitCoin): 26 | print(bitCoin) 27 | case .failure(let error): 28 | print(error) 29 | } 30 | } 31 | } 32 | 33 | func fetchGlobal() { 34 | CryptoCurrencyKit.fetchGlobal(convert: .hkd) { r in 35 | switch r { 36 | case .success(let global): 37 | print(global) 38 | case .failure(let error): 39 | print(error) 40 | } 41 | } 42 | } 43 | 44 | func fetchGraph() { 45 | let dateFormatter = DateFormatter() 46 | dateFormatter.dateFormat = "YYYY-MM-dd" 47 | 48 | let current = Date() 49 | let from = current.addingTimeInterval(-7 * 24 * 60 * 60) 50 | 51 | CryptoCurrencyKit.fetchGraph(.priceUSD, for: "bitcoin", from: from, to: current) { r in 52 | switch r { 53 | case .success(let lines): 54 | print(lines) 55 | case .failure(let error): 56 | print(error) 57 | } 58 | } 59 | } 60 | 61 | fetchGraph() 62 | 63 | RunLoop.main.run() 64 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017, iCell; icell.vip@gmail.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a 4 | copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included 12 | in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 17 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 19 | TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 20 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:4.0 2 | 3 | import PackageDescription 4 | 5 | let package = Package( 6 | name: "CryptoCurrencyKit", 7 | products: [ 8 | .library( 9 | name: "CryptoCurrencyKit", 10 | targets: ["CryptoCurrencyKit"]), 11 | ], 12 | targets: [ 13 | .target( 14 | name: "CryptoCurrencyKit", 15 | path: ".", 16 | sources: ["Sources"]) 17 | ] 18 | ) 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CryptoCurrencyKit 2 | 3 | 4 | CryptoCurrencyKit is an API kit based on [CryptoCurrency Market Capitalizations](https://coinmarketcap.com/api/) 5 | 6 | 7 | ## Requirements 8 | 9 | - iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ 10 | - Xcode 9.0+ 11 | - Swift 4.0+ 12 | 13 | ## Installation 14 | 15 | ### CocoaPods 16 | 17 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command: 18 | 19 | ```bash 20 | $ gem install cocoapods 21 | ``` 22 | 23 | To integrate CryptoCurrencyKit into your Xcode project using CocoaPods, specify it in your `Podfile`: 24 | 25 | ```ruby 26 | source 'https://github.com/CocoaPods/Specs.git' 27 | platform :ios, '10.0' 28 | use_frameworks! 29 | 30 | target '' do 31 | pod 'CryptoCurrencyKit' 32 | end 33 | ``` 34 | 35 | Then, run the following command: 36 | 37 | ```bash 38 | $ pod install 39 | ``` 40 | 41 | ### Carthage 42 | 43 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. 44 | 45 | You can install Carthage with [Homebrew](http://brew.sh/) using the following command: 46 | 47 | ```bash 48 | $ brew update 49 | $ brew install carthage 50 | ``` 51 | 52 | To integrate CryptoCurrencyKit into your Xcode project using Carthage, specify it in your `Cartfile`: 53 | 54 | ```ogdl 55 | github "iCell/CryptoCurrencyKit" 56 | ``` 57 | 58 | Run `carthage update` to build the framework and drag the built `CryptoCurrencyKit.framework` into your Xcode project. 59 | 60 | ### Swift Package Manager 61 | 62 | The [Swift Package Manager](https://swift.org/package-manager/) is a tool for automating the distribution of Swift code and is integrated into the `swift` compiler. It is in early development, but Alamofire does support its use on supported platforms. 63 | 64 | Once you have your Swift package set up, adding Alamofire as a dependency is as easy as adding it to the `dependencies` value of your `Package.swift`. 65 | 66 | ```swift 67 | dependencies: [ 68 | .Package(url: "https://github.com/iCell/CryptoCurrency.git") 69 | ] 70 | ``` 71 | 72 | ## Usage 73 | 74 | fetch tickers 75 | 76 | ```Swift 77 | CryptoCurrencyKit.fetchTickers { response in 78 | switch response { 79 | case .success(let data): 80 | print(data) 81 | case .failure(let error): 82 | print(error) 83 | } 84 | } 85 | ``` 86 | 87 | fetch a specific crypto currency 88 | 89 | ```Swift 90 | CryptoCurrencyKit.fetchTicker(coinName: "BitCoin", convert: .jpy) { response in 91 | switch response { 92 | case .success(let bitCoin): 93 | print(bitCoin.priceJPY) 94 | case .failure(let error): 95 | print(error) 96 | } 97 | } 98 | ``` 99 | 100 | fetch global data 101 | 102 | ```Swift 103 | CryptoCurrencyKit.fetchGlobal(convert: .cny) { response in 104 | switch response { 105 | case .success(let data): 106 | print(data) 107 | case .failure(let error): 108 | print(error) 109 | } 110 | } 111 | ``` 112 | 113 | ## Author 114 | 115 | iCell, icell.vip@gmail.com 116 | 117 | ## License 118 | 119 | Alamofire is released under the MIT license. [See LICENSE](https://github.com/iCell/CryptoCurrency/blob/master/LICENSE) for details. 120 | -------------------------------------------------------------------------------- /Sources/CryptoCurrencyKit.swift: -------------------------------------------------------------------------------- 1 | import Foundation 2 | 3 | public struct CryptoCurrencyKit { 4 | 5 | public static func fetchTickers(convert: Money = .usd, limit: Int? = nil, response: ((_ r: ResponseA) -> Void)?) { 6 | var urlString = "https://api.coinmarketcap.com/v1/ticker/" 7 | urlString.append("?convert=\(convert.rawValue)") 8 | if let limit = limit { 9 | urlString.append("&limit=\(limit)") 10 | } 11 | let url = URL(string: urlString)! 12 | let urlRequest = URLRequest(url: url) 13 | requestA(urlRequest: urlRequest, response: response) 14 | } 15 | 16 | public static func fetchTicker(coinName: String, convert: Money = .usd, response: ((_ r: ResponseD) -> Void)?) { 17 | var urlString = "https://api.coinmarketcap.com/v1/ticker/" 18 | urlString.append(coinName) 19 | urlString.append("/?convert=\(convert.rawValue)") 20 | let urlRequest = URLRequest(url: URL(string: urlString)!) 21 | let closure: ((ResponseA) -> Void)? = { r in 22 | switch r { 23 | case .success(let data): 24 | response?(ResponseD.success(data[0])) 25 | case .failure(let error): 26 | response?(ResponseD.failure(error: error)) 27 | } 28 | } 29 | requestA(urlRequest: urlRequest, response: closure) 30 | } 31 | 32 | public static func fetchGlobal(convert: Money = .usd, response: ((_ r: ResponseD) -> Void)?) { 33 | let urlRequest = URLRequest(url: URL(string: "https://api.coinmarketcap.com/v1/global/")!) 34 | requestD(urlRequest: urlRequest, response: response) 35 | } 36 | 37 | public static func fetchGraph(_ graph: Graph, for coin: String, from fromDate: Date, to toDate: Date, response: ((_ r: ResponseA) -> Void)?) { 38 | let fromInterval = Int(fromDate.timeIntervalSince1970 * 1000) 39 | let toInterval = Int(toDate.timeIntervalSince1970 * 1000) 40 | let urlRequest = URLRequest(url: URL(string: "https://graphs.coinmarketcap.com/currencies/\(coin)/\(fromInterval)/\(toInterval)/")!) 41 | requestRaw(urlRequest: urlRequest) { r in 42 | switch r { 43 | case .success(let data): 44 | do { 45 | if let decoded = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: [[Double]]], let values = decoded[graph.rawValue] { 46 | let lines = values.flatMap { ele -> GraphLine? in 47 | if ele.count == 2 { 48 | return GraphLine(value: ele[1], timestamp: ele[0]) 49 | } else { 50 | return nil 51 | } 52 | } 53 | response?(ResponseA.success(lines)) 54 | } else { 55 | response?(ResponseA.failure(error: CCKError.invalidResponse)) 56 | } 57 | } catch { 58 | response?(ResponseA.failure(error: error)) 59 | } 60 | case .failure(let error): 61 | response?(ResponseA.failure(error: error)) 62 | } 63 | } 64 | } 65 | } 66 | 67 | extension CryptoCurrencyKit { 68 | public enum Money: String { 69 | case usd = "USD" 70 | case eur = "EUR" 71 | case gbp = "GBP" 72 | case jpy = "JPY" 73 | case cny = "CNY" 74 | case hkd = "HKD" 75 | 76 | public var symbol: String { 77 | switch self { 78 | case .cny: 79 | return "¥" 80 | case .eur: 81 | return "€" 82 | case .gbp: 83 | return "£" 84 | case .jpy: 85 | return "¥" 86 | case .usd: 87 | return "$" 88 | case .hkd: 89 | return "$" 90 | } 91 | } 92 | 93 | public static var allValues: [Money] { 94 | return [.usd, .eur, .gbp, .jpy, .cny, .hkd] 95 | } 96 | 97 | public static var allRawValues: [String] { 98 | return allValues.map { $0.rawValue } 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /Sources/Global.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Global.swift 3 | // CoinCurrency 4 | // 5 | // Created by Xiaoyu Li on 19/09/2017. 6 | // 7 | 8 | public struct Global { 9 | public let bitCoinPercentageOfMarketCap: Double 10 | public let activeCurrencies: Int 11 | public let activeAssets: Int 12 | public let activeMarkets: Int 13 | 14 | public let totalMarketCapUSD: Double 15 | public let totalVolumeUSD24h: Double 16 | 17 | public let totalMarketCapEUR: Double? 18 | public let totalVolumeEUR24h: Double? 19 | 20 | public let totalMarketCapGBP: Double? 21 | public let totalVolumeGBP24h: Double? 22 | 23 | public let totalMarketCapJPY: Double? 24 | public let totalVolumeJPY24h: Double? 25 | 26 | public let totalMarketCapCNY: Double? 27 | public let totalVolumeCNY24h: Double? 28 | 29 | public let totalMarketCapHKD: Double? 30 | public let totalVolumeHKD24h: Double? 31 | 32 | enum CodingKeys: String, CodingKey { 33 | case bitCoinPercentageOfMarketCap = "bitcoin_percentage_of_market_cap" 34 | case activeCurrencies = "active_currencies" 35 | case activeAssets = "active_assets" 36 | case activeMarkets = "active_markets" 37 | 38 | case totalMarketCapUSD = "total_market_cap_usd" 39 | case totalVolumeUSD24h = "total_24h_volume_usd" 40 | 41 | case totalMarketCapEUR = "total_market_cap_eur" 42 | case totalVolumeEUR24h = "total_24h_volume_eur" 43 | 44 | case totalMarketCapGBP = "total_market_cap_gbp" 45 | case totalVolumeGBP24h = "total_24h_volume_gbp" 46 | 47 | case totalMarketCapJPY = "total_market_cap_jpy" 48 | case totalVolumeJPY24h = "total_24h_volume_jpy" 49 | 50 | case totalMarketCapCNY = "total_market_cap_cny" 51 | case totalVolumeCNY24h = "total_24h_volume_cny" 52 | 53 | case totalMarketCapHKD = "total_market_cap_hkd" 54 | case totalVolumeHKD24h = "total_24h_volume_hkd" 55 | } 56 | } 57 | 58 | extension Global { 59 | public init(activeCurrencies: Int, bitCoinPercentageOfMarketCap: Double, activeAssets: Int, activeMarkets: Int, totalMarketCapUSD: Double, totalVolumeUSD24h: Double, totalMarketCapEUR: Double?, totalVolumeEUR24h: Double?, totalMarketCapGBP: Double?, totalVolumeGBP24h: Double?, totalMarketCapJPY: Double?, totalVolumeJPY24h: Double?, totalMarketCapCNY: Double?, totalVolumeCNY24h: Double?, totalMarketCapHKD: Double?, totalVolumeHKD24h: Double?) { 60 | self.init(bitCoinPercentageOfMarketCap: bitCoinPercentageOfMarketCap, activeCurrencies: activeCurrencies, activeAssets: activeAssets, activeMarkets: activeMarkets, totalMarketCapUSD: totalMarketCapUSD, totalVolumeUSD24h: totalVolumeUSD24h, totalMarketCapEUR: totalMarketCapEUR, totalVolumeEUR24h: totalVolumeEUR24h, totalMarketCapGBP: totalMarketCapGBP, totalVolumeGBP24h: totalVolumeGBP24h, totalMarketCapJPY: totalMarketCapJPY, totalVolumeJPY24h: totalVolumeJPY24h, totalMarketCapCNY: totalMarketCapCNY, totalVolumeCNY24h: totalVolumeCNY24h, totalMarketCapHKD: totalMarketCapHKD, totalVolumeHKD24h: totalVolumeHKD24h) 61 | } 62 | } 63 | 64 | extension Global: Encodable { 65 | public func encode(to encoder: Encoder) throws { 66 | var container = encoder.container(keyedBy: CodingKeys.self) 67 | try container.encode(bitCoinPercentageOfMarketCap, forKey: .bitCoinPercentageOfMarketCap) 68 | try container.encode(activeCurrencies, forKey: .activeCurrencies) 69 | try container.encode(activeAssets, forKey: .activeAssets) 70 | try container.encode(activeMarkets, forKey: .activeMarkets) 71 | try container.encode(totalMarketCapUSD, forKey: .totalMarketCapUSD) 72 | try container.encode(totalVolumeUSD24h, forKey: .totalVolumeUSD24h) 73 | try container.encode(totalMarketCapEUR, forKey: .totalMarketCapEUR) 74 | try container.encode(totalVolumeEUR24h, forKey: .totalVolumeEUR24h) 75 | try container.encode(totalMarketCapGBP, forKey: .totalMarketCapGBP) 76 | try container.encode(totalVolumeGBP24h, forKey: .totalVolumeGBP24h) 77 | try container.encode(totalMarketCapJPY, forKey: .totalMarketCapJPY) 78 | try container.encode(totalVolumeJPY24h, forKey: .totalVolumeJPY24h) 79 | try container.encode(totalMarketCapCNY, forKey: .totalMarketCapCNY) 80 | try container.encode(totalVolumeCNY24h, forKey: .totalVolumeCNY24h) 81 | try container.encode(totalMarketCapHKD, forKey: .totalMarketCapHKD) 82 | try container.encode(totalVolumeHKD24h, forKey: .totalVolumeHKD24h) 83 | } 84 | } 85 | 86 | extension Global: Decodable { 87 | public init(from decoder: Decoder) throws { 88 | let values = try decoder.container(keyedBy: CodingKeys.self) 89 | bitCoinPercentageOfMarketCap = try values.decode(Double.self, forKey: .bitCoinPercentageOfMarketCap) 90 | activeCurrencies = try values.decode(Int.self, forKey: .activeCurrencies) 91 | activeAssets = try values.decode(Int.self, forKey: .activeAssets) 92 | activeMarkets = try values.decode(Int.self, forKey: .activeMarkets) 93 | totalMarketCapUSD = try values.decode(Double.self, forKey: .totalMarketCapUSD) 94 | totalVolumeUSD24h = try values.decode(Double.self, forKey: .totalVolumeUSD24h) 95 | totalMarketCapEUR = try? values.decode(Double.self, forKey: .totalMarketCapEUR) 96 | totalVolumeEUR24h = try? values.decode(Double.self, forKey: .totalVolumeEUR24h) 97 | totalMarketCapGBP = try? values.decode(Double.self, forKey: .totalMarketCapGBP) 98 | totalVolumeGBP24h = try? values.decode(Double.self, forKey: .totalVolumeGBP24h) 99 | totalMarketCapJPY = try? values.decode(Double.self, forKey: .totalMarketCapJPY) 100 | totalVolumeJPY24h = try? values.decode(Double.self, forKey: .totalVolumeJPY24h) 101 | totalMarketCapCNY = try? values.decode(Double.self, forKey: .totalMarketCapCNY) 102 | totalVolumeCNY24h = try? values.decode(Double.self, forKey: .totalVolumeCNY24h) 103 | totalMarketCapHKD = try? values.decode(Double.self, forKey: .totalMarketCapHKD) 104 | totalVolumeHKD24h = try? values.decode(Double.self, forKey: .totalVolumeHKD24h) 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /Sources/Graph.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Graph.swift 3 | // CryptoCurrencyKit 4 | // 5 | // Created by Xiaoyu Li on 30/09/2017. 6 | // 7 | 8 | import Foundation 9 | 10 | public enum Graph: String { 11 | case marketCap = "market_cap_by_available_supply" 12 | case priceUSD = "price_usd" 13 | case priceBTC = "price_btc" 14 | } 15 | 16 | public struct GraphLine: Codable { 17 | public let value: Double 18 | public let timestamp: Double 19 | } 20 | -------------------------------------------------------------------------------- /Sources/Request.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Request.swift 3 | // CryptoCurrencyKit 4 | // 5 | // Created by Xiaoyu Li on 30/09/2017. 6 | // 7 | 8 | import Foundation 9 | 10 | public enum CCKError: Error { 11 | case invalidResponse 12 | } 13 | 14 | extension CryptoCurrencyKit { 15 | 16 | public enum ResponseD { 17 | case failure(error: Error) 18 | case success(T) 19 | } 20 | 21 | public enum ResponseA { 22 | case failure(error: Error) 23 | case success([T]) 24 | } 25 | 26 | public enum ResponseRaw { 27 | case failure(error: Error) 28 | case success(raw: Data) 29 | } 30 | 31 | static func requestA(urlRequest: URLRequest, response: ((_ r: ResponseA) -> Void)?) { 32 | URLSession.shared.dataTask(with: urlRequest) { (data, _, error) in 33 | DispatchQueue.main.async { 34 | if let data = data { 35 | do { 36 | let objects = try JSONDecoder().decode([T].self, from: data) 37 | response?(ResponseA.success(objects)) 38 | } catch let decodeE { 39 | response?(ResponseA.failure(error: decodeE)) 40 | } 41 | } else if let error = error { 42 | response?(ResponseA.failure(error: error)) 43 | } else { 44 | response?(ResponseA.failure(error: CCKError.invalidResponse)) 45 | } 46 | } 47 | }.resume() 48 | } 49 | 50 | static func requestD(urlRequest: URLRequest, response: ((_ r: ResponseD) -> Void)?) { 51 | URLSession.shared.dataTask(with: urlRequest) { (data, _, error) in 52 | DispatchQueue.main.async { 53 | if let data = data { 54 | do { 55 | let object = try JSONDecoder().decode(T.self, from: data) 56 | response?(ResponseD.success(object)) 57 | } catch let decodeE { 58 | response?(ResponseD.failure(error: decodeE)) 59 | } 60 | } else if let error = error { 61 | response?(ResponseD.failure(error: error)) 62 | } else { 63 | response?(ResponseD.failure(error: CCKError.invalidResponse)) 64 | } 65 | } 66 | }.resume() 67 | } 68 | 69 | static func requestRaw(urlRequest: URLRequest, response: ((_ r: ResponseRaw) -> Void)?) { 70 | URLSession.shared.dataTask(with: urlRequest) { (data, _, error) in 71 | DispatchQueue.main.async { 72 | if let data = data { 73 | response?(ResponseRaw.success(raw: data)) 74 | } else if let error = error { 75 | response?(ResponseRaw.failure(error: error)) 76 | } else { 77 | response?(ResponseRaw.failure(error: CCKError.invalidResponse)) 78 | } 79 | } 80 | }.resume() 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Sources/Ticker.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Ticker.swift 3 | // CoinCurrency 4 | // 5 | // Created by Xiaoyu Li on 19/09/2017. 6 | // 7 | 8 | public struct Ticker { 9 | public let id: String 10 | public let name: String 11 | public let symbol: String 12 | public let rank: Int 13 | 14 | public let availableSupply: Double? 15 | public let totalSupply: Double? 16 | public let percentChange1h: Double? 17 | public let percentChange24h: Double? 18 | public let percentChange7d: Double? 19 | public let lastUpdated: Double? 20 | 21 | public let priceBTC: Double? 22 | 23 | public let priceUSD: Double? 24 | public let volumeUSD24h: Double? 25 | public let marketCapUSD: Double? 26 | 27 | public let priceEUR: Double? 28 | public let volumeEUR24h: Double? 29 | public let marketCapEUR: Double? 30 | 31 | public let priceGBP: Double? 32 | public let volumeGBP24h: Double? 33 | public let marketCapGBP: Double? 34 | 35 | public let priceJPY: Double? 36 | public let volumeJPY24h: Double? 37 | public let marketCapJPY: Double? 38 | 39 | public let priceCNY: Double? 40 | public let volumeCNY24h: Double? 41 | public let marketCapCNY: Double? 42 | 43 | public let priceHKD: Double? 44 | public let volumeHKD24h: Double? 45 | public let marketCapHKD: Double? 46 | 47 | enum CodingKeys: String, CodingKey { 48 | case id 49 | case name 50 | case symbol 51 | case rank 52 | 53 | case availableSupply = "available_supply" 54 | case totalSupply = "total_supply" 55 | case percentChange1h = "percent_change_1h" 56 | case percentChange24h = "percent_change_24h" 57 | case percentChange7d = "percent_change_7d" 58 | case lastUpdated = "last_updated" 59 | 60 | case priceBTC = "price_btc" 61 | 62 | case priceUSD = "price_usd" 63 | case volumeUSD24h = "24h_volume_usd" 64 | case marketCapUSD = "market_cap_usd" 65 | 66 | case priceEUR = "price_eur" 67 | case volumeEUR24h = "24h_volume_eur" 68 | case marketCapEUR = "market_cap_eur" 69 | 70 | case priceGBP = "price_gbp" 71 | case volumeGBP24h = "24h_volume_gbp" 72 | case marketCapGBP = "market_cap_gbp" 73 | 74 | case priceHKD = "price_hkd" 75 | case volumeHKD24h = "24h_volume_hkd" 76 | case marketCapHKD = "market_cap_hkd" 77 | 78 | case priceJPY = "price_jpy" 79 | case volumeJPY24h = "24h_volume_jpy" 80 | case marketCapJPY = "market_cap_jpy" 81 | 82 | case priceCNY = "price_cny" 83 | case volumeCNY24h = "24h_volume_cny" 84 | case marketCapCNY = "market_cap_cny" 85 | } 86 | } 87 | 88 | extension Ticker: Equatable { 89 | public static func ==(lhs: Ticker, rhs: Ticker) -> Bool { 90 | return lhs.id.hashValue == rhs.id.hashValue 91 | } 92 | } 93 | 94 | extension Ticker { 95 | public func price(for money: CryptoCurrencyKit.Money) -> Double? { 96 | switch money { 97 | case .cny: 98 | return priceCNY 99 | case .usd: 100 | return priceUSD 101 | case .eur: 102 | return priceEUR 103 | case .gbp: 104 | return priceGBP 105 | case .hkd: 106 | return priceHKD 107 | case .jpy: 108 | return priceJPY 109 | } 110 | } 111 | 112 | public func volume24h(for money: CryptoCurrencyKit.Money) -> Double? { 113 | switch money { 114 | case .cny: 115 | return volumeCNY24h 116 | case .usd: 117 | return volumeUSD24h 118 | case .eur: 119 | return volumeEUR24h 120 | case .gbp: 121 | return volumeGBP24h 122 | case .hkd: 123 | return volumeHKD24h 124 | case .jpy: 125 | return volumeJPY24h 126 | } 127 | } 128 | 129 | public func marketCap(for money: CryptoCurrencyKit.Money) -> Double? { 130 | switch money { 131 | case .cny: 132 | return marketCapCNY 133 | case .usd: 134 | return marketCapUSD 135 | case .eur: 136 | return marketCapEUR 137 | case .gbp: 138 | return marketCapGBP 139 | case .hkd: 140 | return marketCapHKD 141 | case .jpy: 142 | return marketCapJPY 143 | } 144 | } 145 | } 146 | 147 | extension Ticker: Encodable { 148 | public func encode(to encoder: Encoder) throws { 149 | var container = encoder.container(keyedBy: CodingKeys.self) 150 | try container.encode(id, forKey: .id) 151 | try container.encode(name, forKey: .name) 152 | try container.encode(symbol, forKey: .symbol) 153 | try container.encode(rank, forKey: .rank) 154 | try container.encode(availableSupply, forKey: .availableSupply) 155 | try container.encode(totalSupply, forKey: .totalSupply) 156 | try container.encode(percentChange1h, forKey: .percentChange1h) 157 | try container.encode(percentChange24h, forKey: .percentChange24h) 158 | try container.encode(percentChange7d, forKey: .percentChange7d) 159 | try container.encode(lastUpdated, forKey: .lastUpdated) 160 | try container.encode(priceBTC, forKey: .priceBTC) 161 | try container.encode(priceUSD, forKey: .priceUSD) 162 | try container.encode(volumeUSD24h, forKey: .volumeUSD24h) 163 | try container.encode(marketCapUSD, forKey: .marketCapUSD) 164 | try container.encode(priceEUR, forKey: .priceEUR) 165 | try container.encode(volumeEUR24h, forKey: .volumeEUR24h) 166 | try container.encode(marketCapEUR, forKey: .marketCapEUR) 167 | try container.encode(priceGBP, forKey: .priceGBP) 168 | try container.encode(volumeGBP24h, forKey: .volumeGBP24h) 169 | try container.encode(marketCapGBP, forKey: .marketCapGBP) 170 | try container.encode(priceCNY, forKey: .priceCNY) 171 | try container.encode(volumeCNY24h, forKey: .volumeCNY24h) 172 | try container.encode(marketCapCNY, forKey: .marketCapCNY) 173 | try container.encode(priceHKD, forKey: .priceHKD) 174 | try container.encode(volumeHKD24h, forKey: .volumeHKD24h) 175 | try container.encode(marketCapHKD, forKey: .marketCapHKD) 176 | try container.encode(priceJPY, forKey: .priceJPY) 177 | try container.encode(volumeJPY24h, forKey: .volumeJPY24h) 178 | try container.encode(marketCapJPY, forKey: .marketCapJPY) 179 | } 180 | } 181 | 182 | extension Ticker { 183 | public init(id: String, symbol: String, name: String, rank: Int, availableSupply: Double?, totalSupply: Double?, percentChange1h: Double?, percentChange24h: Double?, percentChange7d: Double?, lastUpdated: Double?, priceBTC: Double?, priceUSD: Double?, volumeUSD24h: Double?, marketCapUSD: Double?, priceEUR: Double?, volumeEUR24h: Double?, marketCapEUR: Double?, priceGBP: Double?, volumeGBP24h: Double?, marketCapGBP: Double?, priceJPY: Double?, volumeJPY24h: Double?, marketCapJPY: Double?, priceCNY: Double?, volumeCNY24h: Double?, marketCapCNY: Double?, priceHKD: Double?, volumeHKD24h: Double?, marketCapHKD: Double?) { 184 | self.init(id: id, name: name, symbol: symbol, rank: rank, availableSupply: availableSupply, totalSupply: totalSupply, percentChange1h: percentChange1h, percentChange24h: percentChange24h, percentChange7d: percentChange7d, lastUpdated: lastUpdated, priceBTC: priceBTC, priceUSD: priceUSD, volumeUSD24h: volumeUSD24h, marketCapUSD: marketCapUSD, priceEUR: priceEUR, volumeEUR24h: volumeUSD24h, marketCapEUR: marketCapEUR, priceGBP: priceGBP, volumeGBP24h: volumeGBP24h, marketCapGBP: marketCapGBP, priceJPY: priceJPY, volumeJPY24h: volumeJPY24h, marketCapJPY: marketCapJPY, priceCNY: priceCNY, volumeCNY24h: volumeCNY24h, marketCapCNY: marketCapCNY, priceHKD: priceHKD, volumeHKD24h: volumeHKD24h, marketCapHKD: marketCapHKD) 185 | } 186 | } 187 | 188 | extension Ticker: Decodable { 189 | public init(from decoder: Decoder) throws { 190 | let values = try decoder.container(keyedBy: CodingKeys.self) 191 | id = try values.decode(String.self, forKey: .id) 192 | name = try values.decode(String.self, forKey: .name) 193 | symbol = try values.decode(String.self, forKey: .symbol) 194 | rank = try Int(values.decode(String.self, forKey: .rank))! 195 | 196 | if let availableSupplyTemp = try? values.decode(String.self, forKey: .availableSupply) { 197 | availableSupply = Double(availableSupplyTemp) 198 | } else { 199 | availableSupply = nil 200 | } 201 | if let totalSupplyTemp = try? values.decode(String.self, forKey: .totalSupply) { 202 | totalSupply = Double(totalSupplyTemp) 203 | } else { 204 | totalSupply = nil 205 | } 206 | if let lastUpdatedTemp = try? values.decode(String.self, forKey: .lastUpdated) { 207 | lastUpdated = Double(lastUpdatedTemp) 208 | } else { 209 | lastUpdated = nil 210 | } 211 | 212 | if let priceBTCTemp = try? values.decode(String.self, forKey: .priceBTC) { 213 | priceBTC = Double(priceBTCTemp) 214 | } else { 215 | priceBTC = nil 216 | } 217 | if let priceUSDTemp = try? values.decode(String.self, forKey: .priceUSD) { 218 | priceUSD = Double(priceUSDTemp) 219 | } else { 220 | priceUSD = nil 221 | } 222 | if let volumeUSD24hTemp = try? values.decode(String.self, forKey: .volumeUSD24h) { 223 | volumeUSD24h = Double(volumeUSD24hTemp) 224 | } else { 225 | volumeUSD24h = nil 226 | } 227 | if let marketCapUSDTemp = try? values.decode(String.self, forKey: .marketCapUSD) { 228 | marketCapUSD = Double(marketCapUSDTemp) 229 | } else { 230 | marketCapUSD = nil 231 | } 232 | 233 | if let percentChange1hTemp = try? values.decode(String.self, forKey: .percentChange1h) { 234 | percentChange1h = Double(percentChange1hTemp) 235 | } else { 236 | percentChange1h = nil 237 | } 238 | if let percentChange24hTemp = try? values.decode(String.self, forKey: .percentChange24h) { 239 | percentChange24h = Double(percentChange24hTemp) 240 | } else { 241 | percentChange24h = nil 242 | } 243 | if let percentChange7dtemp = try? values.decode(String.self, forKey: .percentChange7d) { 244 | percentChange7d = Double(percentChange7dtemp) 245 | } else { 246 | percentChange7d = nil 247 | } 248 | 249 | if let priceEURTemp = try? values.decode(String.self, forKey: .priceEUR) { 250 | priceEUR = Double(priceEURTemp) 251 | } else { 252 | priceEUR = nil 253 | } 254 | if let volumeEUR24hTemp = try? values.decode(String.self, forKey: .volumeEUR24h) { 255 | volumeEUR24h = Double(volumeEUR24hTemp) 256 | } else { 257 | volumeEUR24h = nil 258 | } 259 | if let marketCapEURTemp = try? values.decode(String.self, forKey: .marketCapEUR) { 260 | marketCapEUR = Double(marketCapEURTemp) 261 | } else { 262 | marketCapEUR = nil 263 | } 264 | 265 | if let priceGBPTemp = try? values.decode(String.self, forKey: .priceGBP) { 266 | priceGBP = Double(priceGBPTemp) 267 | } else { 268 | priceGBP = nil 269 | } 270 | if let volumeGBP24hTemp = try? values.decode(String.self, forKey: .volumeGBP24h) { 271 | volumeGBP24h = Double(volumeGBP24hTemp) 272 | } else { 273 | volumeGBP24h = nil 274 | } 275 | if let marketCapGBPTemp = try? values.decode(String.self, forKey: .marketCapGBP) { 276 | marketCapGBP = Double(marketCapGBPTemp) 277 | } else { 278 | marketCapGBP = nil 279 | } 280 | 281 | if let priceCNYTemp = try? values.decode(String.self, forKey: .priceCNY) { 282 | priceCNY = Double(priceCNYTemp) 283 | } else { 284 | priceCNY = nil 285 | } 286 | if let volumeCNY24hTemp = try? values.decode(String.self, forKey: .volumeCNY24h) { 287 | volumeCNY24h = Double(volumeCNY24hTemp) 288 | } else { 289 | volumeCNY24h = nil 290 | } 291 | if let marketCapCNYTemp = try? values.decode(String.self, forKey: .marketCapCNY) { 292 | marketCapCNY = Double(marketCapCNYTemp) 293 | } else { 294 | marketCapCNY = nil 295 | } 296 | 297 | if let priceHKDTemp = try? values.decode(String.self, forKey: .priceHKD) { 298 | priceHKD = Double(priceHKDTemp) 299 | } else { 300 | priceHKD = nil 301 | } 302 | if let volumeHKD24hTemp = try? values.decode(String.self, forKey: .volumeHKD24h) { 303 | volumeHKD24h = Double(volumeHKD24hTemp) 304 | } else { 305 | volumeHKD24h = nil 306 | } 307 | if let marketCapHKDTemp = try? values.decode(String.self, forKey: .marketCapHKD) { 308 | marketCapHKD = Double(marketCapHKDTemp) 309 | } else { 310 | marketCapHKD = nil 311 | } 312 | 313 | if let priceJPYTemp = try? values.decode(String.self, forKey: .priceJPY) { 314 | priceJPY = Double(priceJPYTemp) 315 | } else { 316 | priceJPY = nil 317 | } 318 | if let volumeJPY24hTemp = try? values.decode(String.self, forKey: .volumeJPY24h) { 319 | volumeJPY24h = Double(volumeJPY24hTemp) 320 | } else { 321 | volumeJPY24h = nil 322 | } 323 | if let marketCapJPYTemp = try? values.decode(String.self, forKey: .marketCapJPY) { 324 | marketCapJPY = Double(marketCapJPYTemp) 325 | } else { 326 | marketCapJPY = nil 327 | } 328 | } 329 | } 330 | 331 | --------------------------------------------------------------------------------