diff --git a/Constants/Permissions.js b/Constants/Permissions.js
index a6e2d25b..d54f0b85 100644
--- a/Constants/Permissions.js
+++ b/Constants/Permissions.js
@@ -55,6 +55,7 @@ export const Permissions = {
   Zinc: "Zinc",
   Water: "Water",
   DistanceCycling: "DistanceCycling",
+  DistanceSwimming: "DistanceSwimming",
   DistanceWalkingRunning: "DistanceWalkingRunning",
   FlightsClimbed: "FlightsClimbed",
   HeartRate: "HeartRate",
@@ -66,5 +67,6 @@ export const Permissions = {
   SleepAnalysis: "SleepAnalysis",
   StepCount: "StepCount",
   Steps: "Steps",
-  Weight: "Weight"
+  Weight: "Weight",
+  Workout: "Workout"
 }
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.h
index 235e9c6b..5bdecf42 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.h
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.h
@@ -3,8 +3,10 @@
 //  RCTAppleHealthKit
 //
 //  Created by Alexander Vallorosi on 4/27/17.
-//  Copyright © 2017 Alexander Vallorosi. All rights reserved.
+//  This source code is licensed under the MIT-style license found in the
+//  LICENSE file in the root directory of this source tree.
 //
+
 #import "RCTAppleHealthKit.h"
 
 @interface RCTAppleHealthKit (Methods_Activity)
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m
index 03b2724c..378413ea 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Activity.m
@@ -3,8 +3,8 @@
 //  RCTAppleHealthKit
 //
 //  Created by Alexander Vallorosi on 4/27/17.
-//  Copyright © 2017 Alexander Vallorosi. All rights reserved.
-//
+//  This source code is licensed under the MIT-style license found in the
+//  LICENSE file in the root directory of this source tree.
 
 #import "RCTAppleHealthKit+Methods_Activity.h"
 #import "RCTAppleHealthKit+Queries.h"
@@ -35,8 +35,7 @@ - (void)activity_getActiveEnergyBurned:(NSDictionary *)input callback:(RCTRespon
                                   callback(@[[NSNull null], results]);
                                   return;
                               } else {
-                                  NSLog(@"error getting active energy burned samples: %@", error);
-                                  callback(@[RCTMakeError(@"error getting active energy burned samples", nil, nil)]);
+                                  callback(@[RCTJSErrorFromNSError(error)]);
                                   return;
                               }
                           }];
@@ -65,8 +64,7 @@ - (void)activity_getBasalEnergyBurned:(NSDictionary *)input callback:(RCTRespons
                                   callback(@[[NSNull null], results]);
                                   return;
                               } else {
-                                  NSLog(@"error getting basal energy burned samples: %@", error);
-                                  callback(@[RCTMakeError(@"error getting basal energy burned samples", nil, nil)]);
+                                  callback(@[RCTJSErrorFromNSError(error)]);
                                   return;
                               }
                           }];
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h
index 08679742..51b67716 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.h
@@ -23,6 +23,11 @@
 - (void)body_saveHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 
 - (void)body_getLatestBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+- (void)body_getBodyFatPercentageSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+- (void)body_saveBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+
 - (void)body_getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+- (void)body_getLeanBodyMassSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+- (void)body_saveLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 
 @end
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m
index ca11ae22..e3ba841e 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Body.m
@@ -18,22 +18,17 @@ - (void)body_getLatestWeight:(NSDictionary *)input callback:(RCTResponseSenderBl
 {
     HKQuantityType *weightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyMass];
 
-    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input];
-    if(unit == nil){
-        unit = [HKUnit poundUnit];
-    }
-
+    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]];
+    
     [self fetchMostRecentQuantitySampleOfType:weightType
                                     predicate:nil
                                    completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
         if (!mostRecentQuantity) {
-            NSLog(@"error getting latest weight: %@", error);
-            callback(@[RCTMakeError(@"error getting latest weight", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
         }
         else {
             // Determine the weight in the required unit.
             double usersWeight = [mostRecentQuantity doubleValueForUnit:unit];
-
             NSDictionary *response = @{
                     @"value" : @(usersWeight),
                     @"startDate" : [RCTAppleHealthKit buildISO8601StringFromDate:startDate],
@@ -71,8 +66,7 @@ - (void)body_getWeightSamples:(NSDictionary *)input callback:(RCTResponseSenderB
             callback(@[[NSNull null], results]);
             return;
         } else {
-            NSLog(@"error getting weight samples: %@", error);
-            callback(@[RCTMakeError(@"error getting weight samples", nil, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
     }];
@@ -91,8 +85,7 @@ - (void)body_saveWeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)c
 
     [self.healthStore saveObject:weightSample withCompletion:^(BOOL success, NSError *error) {
         if (!success) {
-            NSLog(@"error saving the weight sample: %@", error);
-            callback(@[RCTMakeError(@"error saving the weight sample", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
         callback(@[[NSNull null], @(weight)]);
@@ -108,8 +101,7 @@ - (void)body_getLatestBodyMassIndex:(NSDictionary *)input callback:(RCTResponseS
                                     predicate:nil
                                    completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
         if (!mostRecentQuantity) {
-            NSLog(@"error getting latest BMI: %@", error);
-            callback(@[RCTMakeError(@"error getting latest BMI", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
         }
         else {
             // Determine the bmi in the required unit.
@@ -140,8 +132,7 @@ - (void)body_saveBodyMassIndex:(NSDictionary *)input callback:(RCTResponseSender
 
     [self.healthStore saveObject:bmiSample withCompletion:^(BOOL success, NSError *error) {
         if (!success) {
-            NSLog(@"error saving BMI sample: %@.", error);
-            callback(@[RCTMakeError(@"error saving BMI sample", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
         callback(@[[NSNull null], @(bmi)]);
@@ -152,11 +143,7 @@ - (void)body_saveBodyMassIndex:(NSDictionary *)input callback:(RCTResponseSender
 - (void)body_getLatestHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
 {
     HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
-
-    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input];
-    if(unit == nil){
-        unit = [HKUnit inchUnit];
-    }
+    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]];;
 
     [self fetchMostRecentQuantitySampleOfType:heightType
                                     predicate:nil
@@ -206,8 +193,7 @@ - (void)body_getHeightSamples:(NSDictionary *)input callback:(RCTResponseSenderB
           callback(@[[NSNull null], results]);
           return;
         } else {
-          NSLog(@"error getting height samples: %@", error);
-          callback(@[RCTMakeError(@"error getting height samples", error, nil)]);
+          callback(@[RCTJSErrorFromNSError(error)]);
           return;
         }
     }];
@@ -218,11 +204,7 @@ - (void)body_saveHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)c
 {
     double height = [RCTAppleHealthKit doubleValueFromOptions:input];
     NSDate *sampleDate = [RCTAppleHealthKit dateFromOptionsDefaultNow:input];
-
-    HKUnit *heightUnit = [RCTAppleHealthKit hkUnitFromOptions:input];
-    if(heightUnit == nil){
-        heightUnit = [HKUnit inchUnit];
-    }
+    HKUnit *heightUnit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit inchUnit]];
 
     HKQuantity *heightQuantity = [HKQuantity quantityWithUnit:heightUnit doubleValue:height];
     HKQuantityType *heightType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierHeight];
@@ -230,8 +212,7 @@ - (void)body_saveHeight:(NSDictionary *)input callback:(RCTResponseSenderBlock)c
 
     [self.healthStore saveObject:heightSample withCompletion:^(BOOL success, NSError *error) {
         if (!success) {
-            NSLog(@"error saving height sample: %@", error);
-            callback(@[RCTMakeError(@"error saving height sample", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
         callback(@[[NSNull null], @(height)]);
@@ -247,8 +228,7 @@ - (void)body_getLatestBodyFatPercentage:(NSDictionary *)input callback:(RCTRespo
                                     predicate:nil
                                    completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
         if (!mostRecentQuantity) {
-            NSLog(@"error getting latest body fat percentage: %@", error);
-            callback(@[RCTMakeError(@"error getting latest body fat percentage", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
         }
         else {
             // Determine the weight in the required unit.
@@ -269,6 +249,62 @@ - (void)body_getLatestBodyFatPercentage:(NSDictionary *)input callback:(RCTRespo
 }
 
 
+- (void)body_getBodyFatPercentageSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
+{
+    HKQuantityType *bodyFatPercentType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage];
+    
+    HKUnit *unit = [HKUnit percentUnit];
+    NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit];
+    BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
+    NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
+    NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
+    if(startDate == nil){
+        callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]);
+        return;
+    }
+    NSPredicate * predicate = [RCTAppleHealthKit predicateForSamplesBetweenDates:startDate endDate:endDate];
+    
+    [self fetchQuantitySamplesOfType:bodyFatPercentType
+                                unit:unit
+                           predicate:predicate
+                           ascending:ascending
+                               limit:limit
+                          completion:^(NSArray *results, NSError *error) {
+                              if(results){
+                                  callback(@[[NSNull null], results]);
+                                  return;
+                              } else {
+                                  NSLog(@"error getting body fat percentage samples: %@", error);
+                                  callback(@[RCTMakeError(@"error getting body fat percentage samples", nil, nil)]);
+                                  return;
+                              }
+                          }];
+}
+
+
+- (void)body_saveBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
+{
+    double percentage = [RCTAppleHealthKit doubleValueFromOptions:input];
+    NSDate *sampleDate = [RCTAppleHealthKit dateFromOptionsDefaultNow:input];
+    HKUnit *unit = [HKUnit percentUnit];
+    
+    percentage = percentage / 100;
+
+    HKQuantity *bodyFatPercentQuantity = [HKQuantity quantityWithUnit:unit doubleValue:percentage];
+    HKQuantityType *bodyFatPercentType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierBodyFatPercentage];
+    HKQuantitySample *bodyFatPercentSample = [HKQuantitySample quantitySampleWithType:bodyFatPercentType quantity:bodyFatPercentQuantity startDate:sampleDate endDate:sampleDate];
+    
+    [self.healthStore saveObject:bodyFatPercentSample withCompletion:^(BOOL success, NSError *error) {
+        if (!success) {
+            NSLog(@"error saving body fat percent sample: %@", error);
+            callback(@[RCTMakeError(@"error saving body fat percent sample", error, nil)]);
+            return;
+        }
+        callback(@[[NSNull null], @(percentage)]);
+    }];
+}
+
+
 - (void)body_getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
 {
     HKQuantityType *leanBodyMassType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass];
@@ -277,8 +313,7 @@ - (void)body_getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSe
                                     predicate:nil
                                    completion:^(HKQuantity *mostRecentQuantity, NSDate *startDate, NSDate *endDate, NSError *error) {
         if (!mostRecentQuantity) {
-            NSLog(@"error getting latest lean body mass: %@", error);
-            callback(@[RCTMakeError(@"error getting latest lean body mass", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
         }
         else {
             HKUnit *weightUnit = [HKUnit poundUnit];
@@ -295,4 +330,58 @@ - (void)body_getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSe
     }];
 }
 
+
+- (void)body_getLeanBodyMassSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
+{
+    HKQuantityType *leanBodyMassType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass];
+    
+    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]];
+    NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit];
+    BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
+    NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
+    NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
+    if(startDate == nil){
+        callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]);
+        return;
+    }
+    NSPredicate * predicate = [RCTAppleHealthKit predicateForSamplesBetweenDates:startDate endDate:endDate];
+    
+    [self fetchQuantitySamplesOfType:leanBodyMassType
+                                unit:unit
+                           predicate:predicate
+                           ascending:ascending
+                               limit:limit
+                          completion:^(NSArray *results, NSError *error) {
+                              if(results){
+                                  callback(@[[NSNull null], results]);
+                                  return;
+                              } else {
+                                  NSLog(@"error getting lean body mass samples: %@", error);
+                                  callback(@[RCTMakeError(@"error getting lean body mass samples", nil, nil)]);
+                                  return;
+                              }
+                          }];
+}
+
+
+- (void)body_saveLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
+{
+    double mass = [RCTAppleHealthKit doubleValueFromOptions:input];
+    NSDate *sampleDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:[NSDate date]];
+    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit poundUnit]];
+    
+    HKQuantity *massQuantity = [HKQuantity quantityWithUnit:unit doubleValue:mass];
+    HKQuantityType *massType = [HKQuantityType quantityTypeForIdentifier:HKQuantityTypeIdentifierLeanBodyMass];
+    HKQuantitySample *massSample = [HKQuantitySample quantitySampleWithType:massType quantity:massQuantity startDate:sampleDate endDate:sampleDate];
+    
+    [self.healthStore saveObject:massSample withCompletion:^(BOOL success, NSError *error) {
+        if (!success) {
+            NSLog(@"error saving lean body mass sample: %@", error);
+            callback(@[RCTMakeError(@"error saving lean body mass sample", error, nil)]);
+            return;
+        }
+        callback(@[[NSNull null], @(mass)]);
+    }];
+}
+
 @end
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m
index e030b856..e6266a93 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Characteristic.m
@@ -34,8 +34,7 @@ - (void)characteristic_getBiologicalSex:(NSDictionary *)input callback:(RCTRespo
     }
 
     if(value == nil){
-        NSLog(@"error getting biological sex: %@", error);
-        callback(@[RCTMakeError(@"error getting biological sex", error, nil)]);
+        callback(@[RCTJSErrorFromNSError(error)]);
         return;
     }
 
@@ -52,8 +51,7 @@ - (void)characteristic_getDateOfBirth:(NSDictionary *)input callback:(RCTRespons
     NSDate *dob = [self.healthStore dateOfBirthWithError:&error];
 
     if(error != nil){
-        NSLog(@"error getting date of birth: %@", error);
-        callback(@[RCTMakeError(@"error getting date of birth", error, nil)]);
+        callback(@[RCTJSErrorFromNSError(error)]);
         return;
     }
     if(dob == nil) {
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h
index d575d9de..6f1b007f 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.h
@@ -14,10 +14,13 @@
 - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 - (void)fitness_getHourlyStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+- (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+- (void)fitness_setObserver:(NSDictionary *)input;
 - (void)fitness_saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 - (void)fitness_initializeStepEventObserver:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 - (void)fitness_getDistanceWalkingRunningOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 - (void)fitness_getDailyDistanceWalkingRunningSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+- (void)fitness_getDailyDistanceSwimmingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 - (void)fitness_getDistanceCyclingOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 - (void)fitness_getDailyDistanceCyclingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 - (void)fitness_getFlightsClimbedOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m
index 734ebc1a..0e78680d 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Fitness.m
@@ -34,8 +34,7 @@ - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSen
                                     day:date
                              completion:^(double value, NSDate *startDate, NSDate *endDate, NSError *error) {
         if (!value) {
-            NSLog(@"could not fetch step count for day: %@", error);
-            callback(@[RCTMakeError(@"could not fetch step count for day", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
 
@@ -49,6 +48,52 @@ - (void)fitness_getStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSen
     }];
 }
 
+- (void)fitness_getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
+{
+    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit countUnit]];
+    NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit];
+    BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
+    NSString *type = [RCTAppleHealthKit stringFromOptions:input key:@"type" withDefault:@"Walking"];
+    NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:[NSDate date]];
+    NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
+    
+    NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionStrictStartDate];
+    
+    HKSampleType *samplesType = [RCTAppleHealthKit hkQuantityTypeFromString:type];
+    if ([type isEqual:@"Running"] || [type isEqual:@"Cycling"]) {
+        unit = [HKUnit mileUnit];
+    }
+    NSLog(@"error getting samples: %@", [samplesType identifier]);
+    [self fetchSamplesOfType:samplesType
+                                unit:unit
+                           predicate:predicate
+                           ascending:ascending
+                               limit:limit
+                          completion:^(NSArray *results, NSError *error) {
+                              if(results){
+                                  callback(@[[NSNull null], results]);
+                                  return;
+                              } else {
+                                  NSLog(@"error getting samples: %@", error);
+                                  callback(@[RCTMakeError(@"error getting samples", nil, nil)]);
+                                  return;
+                              }
+                          }];
+}
+
+- (void)fitness_setObserver:(NSDictionary *)input
+{
+    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit countUnit]];
+    NSString *type = [RCTAppleHealthKit stringFromOptions:input key:@"type" withDefault:@"Walking"];
+    
+    HKSampleType *samplesType = [RCTAppleHealthKit hkQuantityTypeFromString:type];
+    if ([type isEqual:@"Running"] || [type isEqual:@"Cycling"]) {
+        unit = [HKUnit mileUnit];
+    }
+    
+    [self setObserverForType:samplesType unit:unit];
+}
+
 
 - (void)fitness_getHourlyStepCountOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
 {
@@ -85,6 +130,9 @@ - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseS
     BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
     NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
     NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
+    NSUInteger period = [RCTAppleHealthKit uintFromOptions:input key:@"period" withDefault:60]; 
+    BOOL includeManuallyAdded = [RCTAppleHealthKit boolFromOptions:input key:@"includeManuallyAdded" withDefault:false];
+    
     if(startDate == nil){
         callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]);
         return;
@@ -94,14 +142,15 @@ - (void)fitness_getDailyStepSamples:(NSDictionary *)input callback:(RCTResponseS
 
     [self fetchCumulativeSumStatisticsCollection:stepCountType
                                             unit:unit
+                                            period:period
                                        startDate:startDate
                                          endDate:endDate
                                        ascending:ascending
                                            limit:limit
+                                           includeManuallyAdded:includeManuallyAdded
                                       completion:^(NSArray *arr, NSError *err){
         if (err != nil) {
-            NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err);
-            callback(@[RCTMakeError(@"error with fetchCumulativeSumStatisticsCollection", err, nil)]);
+            callback(@[RCTJSErrorFromNSError(err)]);
             return;
         }
         callback(@[[NSNull null], arr]);
@@ -127,8 +176,7 @@ - (void)fitness_saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock
 
     [self.healthStore saveObject:sample withCompletion:^(BOOL success, NSError *error) {
         if (!success) {
-            NSLog(@"An error occured saving the step count sample %@. The error was: %@.", sample, error);
-            callback(@[RCTMakeError(@"An error occured saving the step count sample", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
         callback(@[[NSNull null], @(value)]);
@@ -150,9 +198,7 @@ - (void)fitness_initializeStepEventObserver:(NSDictionary *)input callback:(RCTR
                      NSError *error) {
 
          if (error) {
-             // Perform Proper Error Handling Here...
-             NSLog(@"*** An error occured while setting up the stepCount observer. %@ ***", error.localizedDescription);
-             callback(@[RCTMakeError(@"An error occured while setting up the stepCount observer", error, nil)]);
+             callback(@[RCTJSErrorFromNSError(error)]);
              return;
          }
 
@@ -177,8 +223,7 @@ - (void)fitness_getDistanceWalkingRunningOnDay:(NSDictionary *)input callback:(R
 
     [self fetchSumOfSamplesOnDayForType:quantityType unit:unit day:date completion:^(double distance, NSDate *startDate, NSDate *endDate, NSError *error) {
         if (!distance) {
-            NSLog(@"ERROR getting DistanceWalkingRunning: %@", error);
-            callback(@[RCTMakeError(@"ERROR getting DistanceWalkingRunning", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
 
@@ -200,6 +245,8 @@ - (void)fitness_getDailyDistanceWalkingRunningSamples:(NSDictionary *)input call
     BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
     NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
     NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
+    NSUInteger period = [RCTAppleHealthKit uintFromOptions:input key:@"period" withDefault:60];
+    BOOL includeManuallyAdded = [RCTAppleHealthKit boolFromOptions:input key:@"includeManuallyAdded" withDefault:false];
     if(startDate == nil){
         callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]);
         return;
@@ -209,10 +256,12 @@ - (void)fitness_getDailyDistanceWalkingRunningSamples:(NSDictionary *)input call
     
     [self fetchCumulativeSumStatisticsCollection:quantityType
                                             unit:unit
+                                            period:period
                                        startDate:startDate
                                          endDate:endDate
                                        ascending:ascending
                                            limit:limit
+                                           includeManuallyAdded:includeManuallyAdded
                                       completion:^(NSArray *arr, NSError *err){
                                           if (err != nil) {
                                               NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err);
@@ -223,6 +272,39 @@ - (void)fitness_getDailyDistanceWalkingRunningSamples:(NSDictionary *)input call
                                       }];
 }
 
+- (void)fitness_getDailyDistanceSwimmingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
+{
+    HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit meterUnit]];
+    NSUInteger limit = [RCTAppleHealthKit uintFromOptions:input key:@"limit" withDefault:HKObjectQueryNoLimit];
+    BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
+    NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
+    NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
+    NSUInteger period = [RCTAppleHealthKit uintFromOptions:input key:@"period" withDefault:60];
+    BOOL includeManuallyAdded = [RCTAppleHealthKit boolFromOptions:input key:@"includeManuallyAdded" withDefault:false];
+    if(startDate == nil){
+        callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]);
+        return;
+    }
+    
+    HKQuantityType *quantityType = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceSwimming];
+    
+    [self fetchCumulativeSumStatisticsCollection:quantityType
+                                            unit:unit
+                                            period:period
+                                       startDate:startDate
+                                         endDate:endDate
+                                       ascending:ascending
+                                           limit:limit
+                                           includeManuallyAdded:includeManuallyAdded
+                                      completion:^(NSArray *arr, NSError *err){
+                                          if (err != nil) {
+                                              callback(@[RCTJSErrorFromNSError(err)]);
+                                              return;
+                                          }
+                                          callback(@[[NSNull null], arr]);
+                                      }];
+}
+
 - (void)fitness_getDistanceCyclingOnDay:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
 {
     HKUnit *unit = [RCTAppleHealthKit hkUnitFromOptions:input key:@"unit" withDefault:[HKUnit meterUnit]];
@@ -232,8 +314,7 @@ - (void)fitness_getDistanceCyclingOnDay:(NSDictionary *)input callback:(RCTRespo
 
     [self fetchSumOfSamplesOnDayForType:quantityType unit:unit day:date completion:^(double distance, NSDate *startDate, NSDate *endDate, NSError *error) {
         if (!distance) {
-            NSLog(@"ERROR getting DistanceCycling: %@", error);
-            callback(@[RCTMakeError(@"ERROR getting DistanceCycling", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
 
@@ -254,6 +335,8 @@ - (void)fitness_getDailyDistanceCyclingSamples:(NSDictionary *)input callback:(R
     BOOL ascending = [RCTAppleHealthKit boolFromOptions:input key:@"ascending" withDefault:false];
     NSDate *startDate = [RCTAppleHealthKit dateFromOptions:input key:@"startDate" withDefault:nil];
     NSDate *endDate = [RCTAppleHealthKit dateFromOptions:input key:@"endDate" withDefault:[NSDate date]];
+    NSUInteger period = [RCTAppleHealthKit uintFromOptions:input key:@"period" withDefault:60];
+    BOOL includeManuallyAdded = [RCTAppleHealthKit boolFromOptions:input key:@"includeManuallyAdded" withDefault:false];
     if(startDate == nil){
         callback(@[RCTMakeError(@"startDate is required in options", nil, nil)]);
         return;
@@ -263,14 +346,15 @@ - (void)fitness_getDailyDistanceCyclingSamples:(NSDictionary *)input callback:(R
     
     [self fetchCumulativeSumStatisticsCollection:quantityType
                                             unit:unit
+                                            period:period
                                        startDate:startDate
                                          endDate:endDate
                                        ascending:ascending
                                            limit:limit
+                                           includeManuallyAdded:includeManuallyAdded
                                       completion:^(NSArray *arr, NSError *err){
                                           if (err != nil) {
-                                              NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err);
-                                              callback(@[RCTMakeError(@"error with fetchCumulativeSumStatisticsCollection", err, nil)]);
+                                              callback(@[RCTJSErrorFromNSError(err)]);
                                               return;
                                           }
                                           callback(@[[NSNull null], arr]);
@@ -286,8 +370,7 @@ - (void)fitness_getFlightsClimbedOnDay:(NSDictionary *)input callback:(RCTRespon
 
     [self fetchSumOfSamplesOnDayForType:quantityType unit:unit day:date completion:^(double count, NSDate *startDate, NSDate *endDate, NSError *error) {
         if (!count) {
-            NSLog(@"ERROR getting FlightsClimbed: %@", error);
-            callback(@[RCTMakeError(@"ERROR getting FlightsClimbed", error, nil), @(count)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
 
@@ -323,8 +406,7 @@ - (void)fitness_getDailyFlightsClimbedSamples:(NSDictionary *)input callback:(RC
                                            limit:limit
                                       completion:^(NSArray *arr, NSError *err){
                                           if (err != nil) {
-                                              NSLog(@"error with fetchCumulativeSumStatisticsCollection: %@", err);
-                                              callback(@[RCTMakeError(@"error with fetchCumulativeSumStatisticsCollection", err, nil)]);
+                                              callback(@[RCTJSErrorFromNSError(err)]);
                                               return;
                                           }
                                           callback(@[[NSNull null], arr]);
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Mindfulness.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Mindfulness.m
index b14ef813..1dc6dca9 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Mindfulness.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Mindfulness.m
@@ -29,8 +29,7 @@ - (void)mindfulness_saveMindfulSession:(NSDictionary *)input callback:(RCTRespon
 
     [self.healthStore saveObject:sample withCompletion:^(BOOL success, NSError *error) {
         if (!success) {
-            NSLog(@"An error occured saving the mindful session sample %@. The error was: %@.", sample, error);
-            callback(@[RCTMakeError(@"An error occured saving the mindful session sample", error, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
         callback(@[[NSNull null], @(value)]);
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Results.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Results.m
index fd5d0345..a1c1cdea 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Results.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Results.m
@@ -32,8 +32,7 @@ - (void)results_getBloodGlucoseSamples:(NSDictionary *)input callback:(RCTRespon
             callback(@[[NSNull null], results]);
             return;
         } else {
-            NSLog(@"error getting blood glucose samples: %@", error);
-            callback(@[RCTMakeError(@"error getting blood glucose samples", nil, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
     }];
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m
index faba4ed1..0894624e 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Sleep.m
@@ -36,8 +36,7 @@ - (void)sleep_getSleepSamples:(NSDictionary *)input callback:(RCTResponseSenderB
                                              callback(@[[NSNull null], results]);
                                              return;
                                          } else {
-                                             NSLog(@"error getting sleep samples: %@", error);
-                                             callback(@[RCTMakeError(@"error getting sleep samples", nil, nil)]);
+                                             callback(@[RCTJSErrorFromNSError(error)]);
                                              return;
                                          }
                                      }];
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Vitals.m b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Vitals.m
index 74c53cb7..698a1b25 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Vitals.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Methods_Vitals.m
@@ -33,8 +33,7 @@ - (void)vitals_getHeartRateSamples:(NSDictionary *)input callback:(RCTResponseSe
             callback(@[[NSNull null], results]);
             return;
         } else {
-            NSLog(@"error getting heart rate samples: %@", error);
-            callback(@[RCTMakeError(@"error getting heart rate samples", nil, nil)]);
+            callback(@[RCTJSErrorFromNSError(error)]);
             return;
         }
     }];
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h
index fd02bf5c..2a70f001 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.h
@@ -24,6 +24,18 @@
                                      startDate:(NSDate *)startDate
                                        endDate:(NSDate *)endDate
                                     completion:(void (^)(NSArray *, NSError *))completionHandler;
+
+
+- (void)fetchSamplesOfType:(HKSampleType *)quantityType
+                              unit:(HKUnit *)unit
+                         predicate:(NSPredicate *)predicate
+                         ascending:(BOOL)asc
+                             limit:(NSUInteger)lim
+                        completion:(void (^)(NSArray *, NSError *))completion;
+- (void)setObserverForType:(HKSampleType *)quantityType
+                      unit:(HKUnit *)unit;
+
+
 - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType
                               unit:(HKUnit *)unit
                          predicate:(NSPredicate *)predicate
@@ -43,7 +55,15 @@
                                      ascending:(BOOL)asc
                                          limit:(NSUInteger)lim
                                     completion:(void (^)(NSArray *, NSError *))completionHandler;
-
+- (void)fetchCumulativeSumStatisticsCollection:(HKQuantityType *)quantityType
+                                          unit:(HKUnit *)unit
+                                          period:(NSUInteger)period
+                                     startDate:(NSDate *)startDate
+                                       endDate:(NSDate *)endDate
+                                     ascending:(BOOL)asc
+                                         limit:(NSUInteger)lim
+                                         includeManuallyAdded:(BOOL)includeManuallyAdded
+                                    completion:(void (^)(NSArray *, NSError *))completionHandler;
 
 
 - (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m
index d839bdec..cb282377 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Queries.m
@@ -10,8 +10,10 @@
 #import "RCTAppleHealthKit+Queries.h"
 #import "RCTAppleHealthKit+Utils.h"
 
-@implementation RCTAppleHealthKit (Queries)
+#import <React/RCTBridgeModule.h>
+#import <React/RCTEventDispatcher.h>
 
+@implementation RCTAppleHealthKit (Queries)
 
 - (void)fetchMostRecentQuantitySampleOfType:(HKQuantityType *)quantityType
                                   predicate:(NSPredicate *)predicate
@@ -49,7 +51,6 @@ - (void)fetchMostRecentQuantitySampleOfType:(HKQuantityType *)quantityType
     [self.healthStore executeQuery:query];
 }
 
-
 - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType
                               unit:(HKUnit *)unit
                          predicate:(NSPredicate *)predicate
@@ -85,6 +86,8 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType
 
                     NSDictionary *elem = @{
                             @"value" : @(value),
+                            @"sourceName" : [[[sample sourceRevision] source] name],
+                            @"sourceId" : [[[sample sourceRevision] source] bundleIdentifier],
                             @"startDate" : startDateString,
                             @"endDate" : endDateString,
                     };
@@ -106,19 +109,153 @@ - (void)fetchQuantitySamplesOfType:(HKQuantityType *)quantityType
     [self.healthStore executeQuery:query];
 }
 
+- (void)fetchSamplesOfType:(HKSampleType *)type
+                              unit:(HKUnit *)unit
+                         predicate:(NSPredicate *)predicate
+                         ascending:(BOOL)asc
+                             limit:(NSUInteger)lim
+                        completion:(void (^)(NSArray *, NSError *))completion {
+    NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate
+                                                                       ascending:asc];
 
+    // declare the block
+    void (^handlerBlock)(HKSampleQuery *query, NSArray *results, NSError *error);
+    // create and assign the block
+    handlerBlock = ^(HKSampleQuery *query, NSArray *results, NSError *error) {
+        if (!results) {
+            if (completion) {
+                completion(nil, error);
+            }
+            return;
+        }
 
+        if (completion) {
+            NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];
 
+            dispatch_async(dispatch_get_main_queue(), ^{
+                if (type == [HKObjectType workoutType]) {
+                    for (HKWorkout *sample in results) {
+                        double energy =  [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]];
+                        double distance = [[sample totalDistance] doubleValueForUnit:[HKUnit mileUnit]];
+                        NSString *type = [RCTAppleHealthKit stringForHKWorkoutActivityType:[sample workoutActivityType]];
+
+                        NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate];
+                        NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate];
+
+                        bool isTracked = true;
+                        if ([[sample metadata][HKMetadataKeyWasUserEntered] intValue] == 1) {
+                            isTracked = false;
+                        }
+
+                        NSString* device = @"";
+                        if (@available(iOS 11.0, *)) {
+                            device = [[sample sourceRevision] productType];
+                        } else {
+                            device = [[sample device] name];
+                            if (!device) {
+                                device = @"iPhone";
+                            }
+                        }
+
+                        NSDictionary *elem = @{
+                                               @"activityId" : [NSNumber numberWithInt:[sample workoutActivityType]],
+                                               @"activityName" : type,
+                                               @"calories" : @(energy),
+                                               @"tracked" : @(isTracked),
+                                               @"sourceName" : [[[sample sourceRevision] source] name],
+                                               @"sourceId" : [[[sample sourceRevision] source] bundleIdentifier],
+                                               @"device": device,
+                                               @"distance" : @(distance),
+                                               @"start" : startDateString,
+                                               @"end" : endDateString
+                                               };
+
+                        [data addObject:elem];
+                    }
+                } else {
+                    for (HKQuantitySample *sample in results) {
+                        HKQuantity *quantity = sample.quantity;
+                        double value = [quantity doubleValueForUnit:unit];
+
+                        NSString * valueType = @"quantity";
+                        if (unit == [HKUnit mileUnit]) {
+                            valueType = @"distance";
+                        }
+
+                        NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate];
+                        NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate];
+
+                        bool isTracked = true;
+                        if ([[sample metadata][HKMetadataKeyWasUserEntered] intValue] == 1) {
+                            isTracked = false;
+                        }
+
+                        NSString* device = @"";
+                        if (@available(iOS 11.0, *)) {
+                            device = [[sample sourceRevision] productType];
+                        } else {
+                            device = [[sample device] name];
+                            if (!device) {
+                                device = @"iPhone";
+                            }
+                        }
+
+                        NSDictionary *elem = @{
+                                               valueType : @(value),
+                                               @"tracked" : @(isTracked),
+                                               @"sourceName" : [[[sample sourceRevision] source] name],
+                                               @"sourceId" : [[[sample sourceRevision] source] bundleIdentifier],
+                                               @"device": device,
+                                               @"start" : startDateString,
+                                               @"end" : endDateString
+                                               };
+
+                        [data addObject:elem];
+                    }
+                }
 
+                completion(data, error);
+            });
+        }
+    };
 
+    HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:type
+                                                           predicate:predicate
+                                                               limit:lim
+                                                     sortDescriptors:@[timeSortDescriptor]
+                                                      resultsHandler:handlerBlock];
+
+    [self.healthStore executeQuery:query];
+}
 
+- (void)setObserverForType:(HKSampleType *)type
+                      unit:(HKUnit *)unit {
+    HKObserverQuery *query = [[HKObserverQuery alloc] initWithSampleType:type predicate:nil updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError * _Nullable error){
+        if (error) {
+            NSLog(@"*** An error occured while setting up the stepCount observer. %@ ***", error.localizedDescription);
+            return;
+        }
+        [self.bridge.eventDispatcher sendAppEventWithName:@"observer" body:@""];
+
+        // Theoretically, HealthKit expect that copletionHandler would be called at the end of query process,
+        // but it's unclear how to do in in event paradigm
 
+//        dispatch_time_t delay = dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC * 5);
+//        dispatch_after(delay, dispatch_get_main_queue(), ^(void){
+//            completionHandler();
+//        });
+    }];
+
+    [self.healthStore executeQuery:query];
+    [self.healthStore enableBackgroundDeliveryForType:type frequency:HKUpdateFrequencyImmediate withCompletion:^(BOOL success, NSError * _Nullable error) {
+        NSLog(@"success %s print some error %@", success ? "true" : "false", [error localizedDescription]);
+    }];
+}
 
 - (void)fetchSleepCategorySamplesForPredicate:(NSPredicate *)predicate
                                    limit:(NSUInteger)lim
                                    completion:(void (^)(NSArray *, NSError *))completion {
 
-
     NSSortDescriptor *timeSortDescriptor = [[NSSortDescriptor alloc] initWithKey:HKSampleSortIdentifierEndDate
                                                                        ascending:false];
 
@@ -346,10 +483,10 @@ - (void)fetchCumulativeSumStatisticsCollection:(HKQuantityType *)quantityType
                                                      fromDate:[NSDate date]];
     anchorComponents.hour = 0;
     NSDate *anchorDate = [calendar dateFromComponents:anchorComponents];
-
+    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered];
     // Create the query
     HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType
-                                                                           quantitySamplePredicate:nil
+                                                                           quantitySamplePredicate:predicate
                                                                                            options:HKStatisticsOptionCumulativeSum
                                                                                         anchorDate:anchorDate
                                                                                 intervalComponents:interval];
@@ -414,9 +551,87 @@ - (void)fetchCumulativeSumStatisticsCollection:(HKQuantityType *)quantityType
     anchorComponents.hour = 0;
     NSDate *anchorDate = [calendar dateFromComponents:anchorComponents];
     
+    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered];
+    // Create the query
+    HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType
+                                                                           quantitySamplePredicate:predicate
+                                                                                           options:HKStatisticsOptionCumulativeSum
+                                                                                        anchorDate:anchorDate
+                                                                                intervalComponents:interval];
+
+    // Set the results handler
+    query.initialResultsHandler = ^(HKStatisticsCollectionQuery *query, HKStatisticsCollection *results, NSError *error) {
+        if (error) {
+            // Perform proper error handling here
+            NSLog(@"*** An error occurred while calculating the statistics: %@ ***", error.localizedDescription);
+        }
+
+        NSMutableArray *data = [NSMutableArray arrayWithCapacity:1];
+
+        [results enumerateStatisticsFromDate:startDate
+                                      toDate:endDate
+                                   withBlock:^(HKStatistics *result, BOOL *stop) {
+
+                                       HKQuantity *quantity = result.sumQuantity;
+                                       if (quantity) {
+                                           NSDate *startDate = result.startDate;
+                                           NSDate *endDate = result.endDate;
+                                           double value = [quantity doubleValueForUnit:unit];
+
+                                           NSString *startDateString = [RCTAppleHealthKit buildISO8601StringFromDate:startDate];
+                                           NSString *endDateString = [RCTAppleHealthKit buildISO8601StringFromDate:endDate];
+
+                                           NSDictionary *elem = @{
+                                                   @"value" : @(value),
+                                                   @"startDate" : startDateString,
+                                                   @"endDate" : endDateString,
+                                           };
+                                           [data addObject:elem];
+                                       }
+                                   }];
+        // is ascending by default
+        if(asc == false) {
+            [RCTAppleHealthKit reverseNSMutableArray:data];
+        }
+
+        if((lim > 0) && ([data count] > lim)) {
+            NSArray* slicedArray = [data subarrayWithRange:NSMakeRange(0, lim)];
+            NSError *err;
+            completionHandler(slicedArray, err);
+        } else {
+            NSError *err;
+            completionHandler(data, err);
+        }
+    };
+
+    [self.healthStore executeQuery:query];
+}
+
+- (void)fetchCumulativeSumStatisticsCollection:(HKQuantityType *)quantityType
+                                          unit:(HKUnit *)unit
+                                          period:(NSUInteger)period
+                                     startDate:(NSDate *)startDate
+                                       endDate:(NSDate *)endDate
+                                     ascending:(BOOL)asc
+                                         limit:(NSUInteger)lim
+                                         includeManuallyAdded:(BOOL)includeManuallyAdded
+                                    completion:(void (^)(NSArray *, NSError *))completionHandler {
+
+    NSCalendar *calendar = [NSCalendar currentCalendar];
+    NSDateComponents *interval = [[NSDateComponents alloc] init];
+    interval.minute = period;
+
+    NSDateComponents *anchorComponents = [calendar components:NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear
+                                                     fromDate:startDate];
+    //anchorComponents.hour = 0;
+    NSDate *anchorDate = [calendar dateFromComponents:anchorComponents];
+    NSPredicate *predicate = nil;
+    if (includeManuallyAdded == false) {
+        predicate = [NSPredicate predicateWithFormat:@"metadata.%K != YES", HKMetadataKeyWasUserEntered];
+    }
     // Create the query
     HKStatisticsCollectionQuery *query = [[HKStatisticsCollectionQuery alloc] initWithQuantityType:quantityType
-                                                                           quantitySamplePredicate:nil
+                                                                           quantitySamplePredicate:predicate
                                                                                            options:HKStatisticsOptionCumulativeSum
                                                                                         anchorDate:anchorDate
                                                                                 intervalComponents:interval];
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h
index 5cb0891b..c6668c69 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.h
@@ -11,7 +11,11 @@
 
 @interface RCTAppleHealthKit (TypesAndPermissions)
 
+- (NSDictionary *)readPermsDict;
+- (NSDictionary *)writePermsDict;
 - (NSSet *)getReadPermsFromOptions:(NSArray *)options;
 - (NSSet *)getWritePermsFromOptions:(NSArray *)options;
+- (HKObjectType *)getWritePermFromString:(NSString *)string;
+- (NSString *)getAuthorizationStatusString:(HKAuthorizationStatus)status;
 
 @end
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m
index 450c0338..a54f03fb 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+TypesAndPermissions.m
@@ -3,7 +3,8 @@
 //  RCTAppleHealthKit
 //
 //  Created by Greg Wilson on 2016-06-26.
-//  Copyright © 2016 Greg Wilson. All rights reserved.
+//  This source code is licensed under the MIT-style license found in the
+//  LICENSE file in the root directory of this source tree.
 //
 
 #import "RCTAppleHealthKit+TypesAndPermissions.h"
@@ -30,6 +31,7 @@ - (NSDictionary *)readPermsDict {
         @"StepCount" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount],
         @"DistanceWalkingRunning" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning],
         @"DistanceCycling" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling],
+        @"DistanceSwimming" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceSwimming],
         @"BasalEnergyBurned" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierBasalEnergyBurned],
         @"ActiveEnergyBurned" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned],
         @"FlightsClimbed" : [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed],
@@ -49,6 +51,8 @@ - (NSDictionary *)readPermsDict {
         @"SleepAnalysis" : [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis],
         // Mindfulness
         @"MindfulSession" : [HKObjectType categoryTypeForIdentifier:HKCategoryTypeIdentifierMindfulSession],
+        //workouts
+        @"Workout" : [HKObjectType workoutType],
     };
     return readPerms;
 }
@@ -118,7 +122,6 @@ - (NSDictionary *)writePermsDict {
     return writePerms;
 }
 
-
 // Returns HealthKit read permissions from options array
 - (NSSet *)getReadPermsFromOptions:(NSArray *)options {
     NSDictionary *readPermDict = [self readPermsDict];
@@ -150,4 +153,18 @@ - (NSSet *)getWritePermsFromOptions:(NSArray *)options {
     return writePermSet;
 }
 
+- (HKObjectType *)getWritePermFromString:(NSString *)writePerm {
+    return [[self writePermsDict] objectForKey:writePerm];
+}
+- (NSString *)getAuthorizationStatusString:(HKAuthorizationStatus)status {
+    switch (status) {
+        case HKAuthorizationStatusNotDetermined:
+            return @"NotDetermined";
+        case HKAuthorizationStatusSharingDenied:
+            return @"SharingDenied";
+        case HKAuthorizationStatusSharingAuthorized:
+            return @"SharingAuthorized";
+    }
+}
+
 @end
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h
index 4501675e..7d00c782 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.h
@@ -23,7 +23,7 @@
 + (NSDate *)startDateFromOptions:(NSDictionary *)options;
 + (NSDate *)endDateFromOptions:(NSDictionary *)options;
 + (NSDate *)endDateFromOptionsDefaultNow:(NSDictionary *)options;
-+ (HKUnit *)hkUnitFromOptions:(NSDictionary *)options;
++ (HKSampleType *)hkQuantityTypeFromString:(NSString *)type;
 
 + (HKUnit *)hkUnitFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(HKUnit *)defaultValue;
 + (NSUInteger)uintFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(NSUInteger)defaultValue;
@@ -33,5 +33,6 @@
 + (bool)boolFromOptions:(NSDictionary *)options key:(NSString *)key withDefault:(bool)defaultValue;
 
 + (NSMutableArray *)reverseNSMutableArray:(NSMutableArray *)array;
++ (NSString*) stringForHKWorkoutActivityType:(int) enumValue;
 
 @end
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m
index 7e0a834c..f3a2f225 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit+Utils.m
@@ -124,56 +124,20 @@ + (NSDate *)endDateFromOptionsDefaultNow:(NSDictionary *)options {
     return date;
 }
 
-// ==========
-// DEPRECATED
-// ==========
-+ (HKUnit *)hkUnitFromOptions:(NSDictionary *)options {
-    NSString *unitString = [options objectForKey:@"unit"];
-    HKUnit *theUnit;
-
-    if([unitString isEqualToString:@"gram"]){
-        theUnit = [HKUnit gramUnit];
-    }
-    if([unitString isEqualToString:@"pound"]){
-        theUnit = [HKUnit poundUnit];
-    }
-    if([unitString isEqualToString:@"meter"]){
-        theUnit = [HKUnit meterUnit];
-    }
-    if([unitString isEqualToString:@"mile"]){
-        theUnit = [HKUnit mileUnit];
-    }
-    if([unitString isEqualToString:@"inch"]){
-        theUnit = [HKUnit inchUnit];
-    }
-    if([unitString isEqualToString:@"foot"]){
-        theUnit = [HKUnit footUnit];
-    }
-    if([unitString isEqualToString:@"second"]){
-        theUnit = [HKUnit secondUnit];
-    }
-    if([unitString isEqualToString:@"minute"]){
-        theUnit = [HKUnit minuteUnit];
-    }
-    if([unitString isEqualToString:@"hour"]){
-        theUnit = [HKUnit hourUnit];
-    }
-    if([unitString isEqualToString:@"day"]){
-        theUnit = [HKUnit dayUnit];
-    }
-    if([unitString isEqualToString:@"joule"]){
-        theUnit = [HKUnit jouleUnit];
-    }
-    if([unitString isEqualToString:@"calorie"]){
-        theUnit = [HKUnit calorieUnit];
-    }
-    if([unitString isEqualToString:@"count"]){
-        theUnit = [HKUnit countUnit];
-    }
-    if([unitString isEqualToString:@"percent"]){
-        theUnit = [HKUnit percentUnit];
-    }
-    return theUnit;
++ (HKSampleType *)hkQuantityTypeFromString:(NSString *)type {
+    if ([type isEqual:@"Walking"]) {
+        return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierStepCount];
+    } else if ([type isEqual:@"StairClimbing"]) {
+        return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierFlightsClimbed];
+    } else if ([type isEqual:@"Running"]){
+        return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceWalkingRunning];
+    } else if ([type isEqual:@"Cycling"]){
+        return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceCycling];
+    } else if ([type isEqual:@"Swimming"]){
+        return [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierDistanceSwimming];
+    }
+    // default [type isEqual:@"Workout"])
+    return [HKObjectType workoutType];
 }
 
 
@@ -184,12 +148,21 @@ + (HKUnit *)hkUnitFromOptions:(NSDictionary *)options key:(NSString *)key withDe
     if([unitString isEqualToString:@"gram"]){
         theUnit = [HKUnit gramUnit];
     }
+    if([unitString isEqualToString:@"kg"]){
+        theUnit = [HKUnit gramUnitWithMetricPrefix:HKMetricPrefixKilo];
+    }
+    if([unitString isEqualToString:@"stone"]){
+        theUnit = [HKUnit stoneUnit];
+    }
     if([unitString isEqualToString:@"pound"]){
         theUnit = [HKUnit poundUnit];
     }
     if([unitString isEqualToString:@"meter"]){
         theUnit = [HKUnit meterUnit];
     }
+    if([unitString isEqualToString:@"cm"]){
+        theUnit = [HKUnit meterUnitWithMetricPrefix:HKMetricPrefixCenti];
+    }
     if([unitString isEqualToString:@"inch"]){
         theUnit = [HKUnit inchUnit];
     }
@@ -321,4 +294,166 @@ + (NSMutableArray *)reverseNSMutableArray:(NSMutableArray *)array {
     return array;
 }
 
++ (NSString*)stringForHKWorkoutActivityType:(int) enumValue{
+    switch( enumValue ){
+        case HKWorkoutActivityTypeAmericanFootball:
+            return @"AmericanFootball";
+        case HKWorkoutActivityTypeArchery:
+            return @"Archery";
+        case HKWorkoutActivityTypeAustralianFootball:
+            return @"AustralianFootball";
+        case HKWorkoutActivityTypeBadminton:
+            return @"Badminton";
+        case HKWorkoutActivityTypeBaseball:
+            return @"Baseball";
+        case HKWorkoutActivityTypeBasketball:
+            return @"Basketball";
+        case HKWorkoutActivityTypeBowling:
+            return @"Bowling";
+        case HKWorkoutActivityTypeBoxing:
+            return @"Boxing";
+        case HKWorkoutActivityTypeClimbing:
+            return @"Climbing";
+        case HKWorkoutActivityTypeCricket:
+            return @"Cricket";
+        case HKWorkoutActivityTypeCrossTraining:
+            return @"CrossTraining";
+        case HKWorkoutActivityTypeCurling:
+            return @"Curling";
+        case HKWorkoutActivityTypeCycling:
+            return @"Cycling";
+        case HKWorkoutActivityTypeDance:
+            return @"Dance";
+        case HKWorkoutActivityTypeDanceInspiredTraining:
+            return @"DanceInspiredTraining";
+        case HKWorkoutActivityTypeElliptical:
+            return @"Elliptical";
+        case HKWorkoutActivityTypeEquestrianSports:
+            return @"EquestrianSports";
+        case HKWorkoutActivityTypeFencing:
+            return @"Fencing";
+        case HKWorkoutActivityTypeFishing:
+            return @"Fishing";
+        case HKWorkoutActivityTypeFunctionalStrengthTraining:
+            return @"FunctionalStrengthTraining";
+        case HKWorkoutActivityTypeGolf:
+            return @"Golf";
+        case HKWorkoutActivityTypeGymnastics:
+            return @"Gymnastics";
+        case HKWorkoutActivityTypeHandball:
+            return @"Handball";
+        case HKWorkoutActivityTypeHiking:
+            return @"Hiking";
+        case HKWorkoutActivityTypeHockey:
+            return @"Hockey";
+        case HKWorkoutActivityTypeHunting:
+            return @"Hunting";
+        case HKWorkoutActivityTypeLacrosse:
+            return @"Lacrosse";
+        case HKWorkoutActivityTypeMartialArts:
+            return @"MartialArts";
+        case HKWorkoutActivityTypeMindAndBody:
+            return @"MindAndBody";
+        case HKWorkoutActivityTypeMixedMetabolicCardioTraining:
+            return @"MixedMetabolicCardioTraining";
+        case HKWorkoutActivityTypePaddleSports:
+            return @"PaddleSports";
+        case HKWorkoutActivityTypePlay:
+            return @"Play";
+        case HKWorkoutActivityTypePreparationAndRecovery:
+            return @"PreparationAndRecovery";
+        case HKWorkoutActivityTypeRacquetball:
+            return @"Racquetball";
+        case HKWorkoutActivityTypeRowing:
+            return @"Rowing";
+        case HKWorkoutActivityTypeRugby:
+            return @"Rugby";
+        case HKWorkoutActivityTypeRunning:
+            return @"Running";
+        case HKWorkoutActivityTypeSailing:
+            return @"Sailing";
+        case HKWorkoutActivityTypeSkatingSports:
+            return @"SkatingSports";
+        case HKWorkoutActivityTypeSnowSports:
+            return @"SnowSports";
+        case HKWorkoutActivityTypeSoccer:
+            return @"Soccer";
+        case HKWorkoutActivityTypeSoftball:
+            return @"Softball";
+        case HKWorkoutActivityTypeSquash:
+            return @"Squash";
+        case HKWorkoutActivityTypeStairClimbing:
+            return @"StairClimbing";
+        case HKWorkoutActivityTypeSurfingSports:
+            return @"SurfingSports";
+        case HKWorkoutActivityTypeSwimming:
+            return @"Swimming";
+        case HKWorkoutActivityTypeTableTennis:
+            return @"TableTennis";
+        case HKWorkoutActivityTypeTennis:
+            return @"Tennis";
+        case HKWorkoutActivityTypeTrackAndField:
+            return @"TrackAndField";
+        case HKWorkoutActivityTypeTraditionalStrengthTraining:
+            return @"TraditionalStrengthTraining";
+        case HKWorkoutActivityTypeVolleyball:
+            return @"Volleyball";
+        case HKWorkoutActivityTypeWalking:
+            return @"Walking";
+        case HKWorkoutActivityTypeWaterFitness:
+            return @"WaterFitness";
+        case HKWorkoutActivityTypeWaterPolo:
+            return @"WaterPolo";
+        case HKWorkoutActivityTypeWaterSports:
+            return @"WaterSports";
+        case HKWorkoutActivityTypeWrestling:
+            return @"Wrestling";
+        case HKWorkoutActivityTypeYoga:
+            return @"Yoga";
+        case HKWorkoutActivityTypeOther:
+            return @"Other";
+        case HKWorkoutActivityTypeBarre:
+            return @"Barre";
+        case HKWorkoutActivityTypeCoreTraining:
+            return @"CoreTraining";
+        case HKWorkoutActivityTypeCrossCountrySkiing:
+            return @"CrossCountrySkiing";
+        case HKWorkoutActivityTypeDownhillSkiing:
+            return @"DownhillSkiing";
+        case HKWorkoutActivityTypeFlexibility:
+            return @"Flexibility";
+        case HKWorkoutActivityTypeHighIntensityIntervalTraining:
+            return @"HighIntensityIntervalTraining";
+        case HKWorkoutActivityTypeJumpRope:
+            return @"JumpRope";
+        case HKWorkoutActivityTypeKickboxing:
+            return @"Kickboxing";
+        case HKWorkoutActivityTypePilates:
+            return @"Pilates";
+        case HKWorkoutActivityTypeSnowboarding:
+            return @"Snowboarding";
+        case HKWorkoutActivityTypeStairs:
+            return @"Stairs";
+        case HKWorkoutActivityTypeStepTraining:
+            return @"StepTraining";
+        case HKWorkoutActivityTypeWheelchairWalkPace:
+            return @"WheelchairWalkPace";
+        case HKWorkoutActivityTypeWheelchairRunPace:
+            return @"WheelchairRunPace";
+        case HKWorkoutActivityTypeTaiChi:
+            return @"TaiChi";
+        case HKWorkoutActivityTypeMixedCardio:
+            return @"MixedCardio";
+        case HKWorkoutActivityTypeHandCycling:
+            return @"HandCycling";
+        default:{
+            NSException *e = [NSException
+                              exceptionWithName:@"HKWorkoutActivityType InvalidValue"
+                              reason:@"HKWorkoutActivityType can only have a value from the HKWorkoutActivityType enum"
+                              userInfo:nil];
+            @throw e;
+        }
+    }
+}
+
 @end
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.h b/RCTAppleHealthKit/RCTAppleHealthKit.h
index 27b8c036..6ccbe26b 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit.h
+++ b/RCTAppleHealthKit/RCTAppleHealthKit.h
@@ -16,9 +16,11 @@
 @interface RCTAppleHealthKit : NSObject <RCTBridgeModule>
 
 @property (nonatomic) HKHealthStore *healthStore;
+@property BOOL isSync;
 
 - (void)isHealthKitAvailable:(RCTResponseSenderBlock)callback;
 - (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
+- (void)checkPermission:(NSString *)input callback:(RCTResponseSenderBlock)callback;
 - (void)getModuleInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback;
 
 @end
diff --git a/RCTAppleHealthKit/RCTAppleHealthKit.m b/RCTAppleHealthKit/RCTAppleHealthKit.m
index 4e690645..14a1ffa2 100644
--- a/RCTAppleHealthKit/RCTAppleHealthKit.m
+++ b/RCTAppleHealthKit/RCTAppleHealthKit.m
@@ -3,7 +3,8 @@
 //  RCTAppleHealthKit
 //
 //  Created by Greg Wilson on 2016-06-26.
-//  Copyright © 2016 Greg Wilson. All rights reserved.
+//  This source code is licensed under the MIT-style license found in the
+//  LICENSE file in the root directory of this source tree.
 //
 
 #import "RCTAppleHealthKit.h"
@@ -23,6 +24,7 @@
 #import <React/RCTEventDispatcher.h>
 
 @implementation RCTAppleHealthKit
+
 @synthesize bridge = _bridge;
 
 RCT_EXPORT_MODULE();
@@ -97,11 +99,31 @@ @implementation RCTAppleHealthKit
     [self body_getLatestBodyFatPercentage:input callback:callback];
 }
 
+RCT_EXPORT_METHOD(getBodyFatPercentageSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
+{
+    [self body_getBodyFatPercentageSamples:input callback:callback];
+}
+
+RCT_EXPORT_METHOD(saveBodyFatPercentage:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
+{
+    [self body_saveBodyFatPercentage:input callback:callback];
+}
+
 RCT_EXPORT_METHOD(getLatestLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
 {
     [self body_getLatestLeanBodyMass:input callback:callback];
 }
 
+RCT_EXPORT_METHOD(getLeanBodyMassSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
+{
+    [self body_getLeanBodyMassSamples:input callback:callback];
+}
+
+RCT_EXPORT_METHOD(saveLeanBodyMass:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
+{
+    [self body_saveLeanBodyMass:input callback:callback];
+}
+
 RCT_EXPORT_METHOD(getStepCount:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
 {
     [self fitness_getStepCountOnDay:input callback:callback];
@@ -117,6 +139,16 @@ @implementation RCTAppleHealthKit
     [self fitness_getDailyStepSamples:input callback:callback];
 }
 
+RCT_EXPORT_METHOD(getSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
+{
+    [self fitness_getSamples:input callback:callback];
+}
+
+RCT_EXPORT_METHOD(setObserver:(NSDictionary *)input)
+{
+    [self fitness_setObserver:input];
+}
+
 RCT_EXPORT_METHOD(saveSteps:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
 {
     [self fitness_saveSteps:input callback:callback];
@@ -132,6 +164,11 @@ @implementation RCTAppleHealthKit
     [self fitness_getDailyDistanceWalkingRunningSamples:input callback:callback];
 }
 
+RCT_EXPORT_METHOD(getDailyDistanceSwimmingSamples:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
+{
+    [self fitness_getDailyDistanceSwimmingSamples:input callback:callback];
+}
+
 RCT_EXPORT_METHOD(getDistanceCycling:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback)
 {
     [self fitness_getDistanceCyclingOnDay:input callback:callback];
@@ -258,9 +295,7 @@ - (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlo
 
         [self.healthStore requestAuthorizationToShareTypes:writeDataTypes readTypes:readDataTypes completion:^(BOOL success, NSError *error) {
             if (!success) {
-                NSString *errMsg = [NSString stringWithFormat:@"Error with HealthKit authorization: %@", error];
-                NSLog(errMsg);
-                callback(@[RCTMakeError(errMsg, nil, nil)]);
+                callback(@[RCTJSErrorFromNSError(error)]);
                 return;
             } else {
                 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@@ -273,6 +308,28 @@ - (void)initializeHealthKit:(NSDictionary *)input callback:(RCTResponseSenderBlo
     }
 }
 
+RCT_EXPORT_METHOD(authorizationStatusForType:(NSString *)type
+                  resolver:(RCTPromiseResolveBlock)resolve
+                  rejecter:(RCTPromiseRejectBlock)reject
+{
+    if (self.healthStore == nil) {
+        self.healthStore = [[HKHealthStore alloc] init];
+    }
+
+    if ([HKHealthStore isHealthDataAvailable]) {
+        HKObjectType *objectType = [self getWritePermFromString:type];
+        if (objectType == nil) {
+            reject(@"unknown write permission", nil, nil);
+            return;
+        }
+
+        NSString *status = [self getAuthorizationStatusString:[self.healthStore authorizationStatusForType:objectType]];
+        resolve(status);
+    } else {
+        reject(@"HealthKit data is not available", nil, nil);
+    }
+})
+
 - (void)getModuleInfo:(NSDictionary *)input callback:(RCTResponseSenderBlock)callback
 {
     NSDictionary *info = @{
diff --git a/README.md b/README.md
index 0a385f8a..6ad3ead0 100644
--- a/README.md
+++ b/README.md
@@ -77,6 +77,12 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) =>
 ```
 
 ## Changelog
+0.6.5v
+- Enable fetching basal energy [#23](https://github.com/terrillo/rn-apple-healthkit/pull/23)
+- remove checkPermission functions in order to use from PR [#69](https://github.com/terrillo/rn-apple-healthkit/pull/69)
+- Added correct link to permissions. [#73](https://github.com/terrillo/rn-apple-healthkit/pull/73)
+- Add unified way to get workouts + convert Activity Types to name + isTracked flag [#25](https://github.com/terrillo/rn-apple-healthkit/pull/25)
+
 0.6.4v
 - Basal energy ([#23](https://github.com/terrillo/rn-apple-healthkit/pull/23))
 - Fixed issues with saving weight in the past
@@ -95,45 +101,53 @@ AppleHealthKit.initHealthKit(options: Object, (err: string, results: Object) =>
 ## Wiki
   * [Installation](/docs/Install)
   * [Documentation](#documentation)
-    * [Permissions](#permissions)
+    * [Permissions](#supported-apple-permissions)
     * [Units](#units)
     * Base Methods
       * [isAvailable](/docs/isAvailable().md)
       * [initHealthKit](/docs/initHealthKit().md)
+      * [authorizationStatusForType](/docs/authorizationStatusForType().md)
     * Realtime Methods
       * [initStepCountObserver](/docs/initStepCountObserver().md)
+      * [setObserver](/docs/setObserver().md)
     * Read Methods
       * [getActiveEnergyBurned](/docs/getActiveEnergyBurned().md)
       * [getBasalEnergyBurned](/docs/getBasalEnergyBurned().md)
       * [getBiologicalSex](/docs/getBiologicalSex().md)
-      * [getBloodGlucoseSamples](/docs/getbloodglucosesamples().md)
-      * [getBloodPressureSamples](/docs/getbloodpressuresamples().md)
-      * [getBodyTemperatureSamples](/docs/getbodytemperaturesamples().md)
-      * [getDailyDistanceCyclingSamples]()
+      * [getBloodGlucoseSamples](/docs/getBloodglucoseSamples().md)
+      * [getBloodPressureSamples](/docs/getBloodPressureSamples().md)
+      * [getBodyTemperatureSamples](/docs/getBodyTemperatureSamples().md)
+      * [getDailyDistanceCyclingSamples](/docs/getDailyDistanceCyclingSamples().md)
       * [getDailyDistanceWalkingRunningSamples](/docs/getDailyDistanceWalkingRunningSamples().md)
       * [getDailyFlightsClimbedSamples](/docs/getDailyFlightsClimbedSamples().md)
       * [getDailyStepCountSamples](/docs/getDailyStepCountSamples().md)
       * [getDateOfBirth](/docs/getDateOfBirth().md)
-      * [getDistanceCycling](/docs/getdistancecycling().md)
+      * [getDistanceCycling](/docs/getDistanceCycling().md)
+      * [getDistanceSwimming](/docs/getDistanceSwimming().md)
       * [getDistanceWalkingRunning](/docs/getDistanceWalkingRunning().md)
-      * [getFlightsClimbed](/docs/getflightsclimbed().md)
-      * [getHeartRateSamples](/docs/getheartratesamples().md)
-      * [getHeightSamples](/docs/getheightsamples().md)
-      * [getLatestBmi](/docs/getlatestbmi().md)
-      * [getLatestBodyFatPercentage](/docs/getlatestbodyfatpercentage().md)
-      * [getLatestHeight](/docs/getlatestheight().md)
-      * [getLatestLeanBodyMass](/docs/getlatestleanbodymass().md)
-      * [getLatestWeight](/docs/getlatestweight().md)
-      * [getRespiratoryRateSamples](/docs/getrespiratoryratesamples().md)
-      * [getSleepSamples](/docs/getsleepsamples().md)
+      * [getFlightsClimbed](/docs/getFlightsClimbed().md)
+      * [getHeartRateSamples](/docs/getHeartRateSamples().md)
+      * [getHeightSamples](/docs/getHeightSamples().md)
+      * [getLatestBmi](/docs/getLatestBmi().md)
+      * [getLatestBodyFatPercentage](/docs/getLatestBodyFatPercentage().md)
+      * [getBodyFatPercentageSamples](/docs/getBodyFatPercentageSamples().md)
+      * [getLatestHeight](/docs/getLatestHeight().md)
+      * [getLatestLeanBodyMass](/docs/getLatestLeanBodyMass().md)
+      * [getLeanBodyMassSamples](/docs/getLeanBodyMassSamples().md)
+      * [getLatestWeight](/docs/getLatestWeight().md)
+      * [getRespiratoryRateSamples](/docs/getRespiratoryRateSamples().md)
+      * [getSleepSamples](/docs/getSleepSamples().md)
       * [getStepCount](/docs/getStepCount().md)
-      * [getWeightSamples](/docs/getweightsamples().md)
+      * [getWeightSamples](/docs/getWeightSamples().md)
+      * [getSamples](docs/getSamples().md)
     * Write Methods
-      * [saveBmi](/docs/savebmi().md)
-      * [saveHeight](/docs/saveheight().md)
+      * [saveBmi](/docs/saveBmi().md)
+      * [saveHeight](/docs/saveHeight().md)
       * [saveMindfulSession](/docs/saveMindfulSession().md)
-      * [saveWeight](/docs/saveweight().md)
+      * [saveWeight](/docs/saveWeight().md)
       * [saveSteps](/docs/saveSteps().md)
+      * [saveBodyFatPercentage](/docs/saveBodyFatPercentage().md)
+      * [saveLeanBodyMass](/docs/saveLeanBodyMass().md)
   * [References](#references)
 
 ## Supported Apple Permissions
@@ -163,6 +177,7 @@ The available Healthkit permissions to use with `initHealthKit`
 | StepCount              | [HKQuantityTypeIdentifierStepCount](https://developer.apple.com/reference/Healthkit/hkquantitytypeidentifierstepcount?language=objc)                               | ✓    | ✓     |
 | Steps                  | [HKQuantityTypeIdentifierSteps](https://developer.apple.com/reference/Healthkit/hkquantitytypeidentifiersteps?language=objc)                                       | ✓    | ✓     |
 | Weight                 | [HKQuantityTypeIdentifierBodyMass](https://developer.apple.com/reference/Healthkit/hkquantitytypeidentifierbodymass?language=objc)                                 | ✓    | ✓     |
+| BodyFatPercentage      | [HKQuantityTypeIdentifierBodyFatPercentage](https://developer.apple.com/reference/Healthkit/hkquantitytypeidentifierbodyfatpercentage?language=objc)                                 | ✓    | ✓     |
 
 These permissions are exported as constants of the `rn-apple-healthkit` module.
 
diff --git a/docs/authorizationStatusForType().md b/docs/authorizationStatusForType().md
new file mode 100644
index 00000000..8687b89b
--- /dev/null
+++ b/docs/authorizationStatusForType().md
@@ -0,0 +1,16 @@
+Check the authorization status for sharing (writing) the specified data type.
+
+Status will be one of `"NotDetermined"`, `"SharingDenied"`, `"SharingAuthorized"`.
+
+```javascript
+try {
+const status = await AppleHealthKit.authorizationStatusForType("StepCount")
+if (status) {
+  console.log("status is", status)
+}
+} catch (error) {
+  console.warn(error)
+}
+```
+
+There is no way to check authorization status for read permission, [see this](https://developer.apple.com/documentation/healthkit/hkhealthstore/1614154-authorizationstatusfortype?language=objc).
diff --git a/docs/getBloodGlucoseSamples().md b/docs/getBloodGlucoseSamples().md
index 5b2f86f3..a89ebe8f 100644
--- a/docs/getBloodGlucoseSamples().md
+++ b/docs/getBloodGlucoseSamples().md
@@ -10,7 +10,7 @@ let options = {
 ```
 Available units are: `'mmolPerL'`, `'mgPerdL'`.
 
-The callback function will be called with a `samples` array containing objects with *value*, *startDate*, and *endDate* fields
+The callback function will be called with a `samples` array containing objects with *value*, *sourceId*, *sourceName*, *startDate*, and *endDate* fields
 
 ```javascript
 AppleHealthKit.getBloodGlucoseSamples(options, (err: Object, results: Array<Object>) => {
diff --git a/docs/getBodyFatPercentageSamples().md b/docs/getBodyFatPercentageSamples().md
new file mode 100644
index 00000000..8e3e8722
--- /dev/null
+++ b/docs/getBodyFatPercentageSamples().md
@@ -0,0 +1,27 @@
+Query for body fat percentage samples. the options object is used to setup a query to retrieve relevant samples.
+
+```javascript
+let options = {
+  startDate: (new Date(2016,4,27)).toISOString(), // required
+  endDate: (new Date()).toISOString(), // optional; default now
+  ascending: false,	// optional; default false
+  limit:10, // optional; default no limit
+};
+```
+
+```javascript
+AppleHealthKit.getBodyFatPercentageSamples(options, (err: Object, results: Array<Object>) => {
+  if (err) {
+    return;
+  }
+  console.log(results)
+});
+```
+
+```javascript
+[
+  { value: 16.5, startDate: '2016-07-09T00:00:00.000-0400', endDate: '2016-07-10T00:00:00.000-0400' },
+  { value: 16.1, startDate: '2016-07-08T00:00:00.000-0400', endDate: '2016-07-09T00:00:00.000-0400' },
+  { value: 15.9, startDate: '2016-07-07T00:00:00.000-0400', endDate: '2016-07-08T00:00:00.000-0400' },
+]
+```
diff --git a/docs/getDailyDistanceSwimmingSamples().md b/docs/getDailyDistanceSwimmingSamples().md
new file mode 100644
index 00000000..22045149
--- /dev/null
+++ b/docs/getDailyDistanceSwimmingSamples().md
@@ -0,0 +1,19 @@
+```javascript
+let options = {
+  startDate: (new Date(2016,4,27)).toISOString(), // required
+  endDate: (new Date()).toISOString(), // optional; default now
+  ascending: false,	// optional; default false
+  limit:10, // optional; default no limit
+  period: 60, // time interval in minutes optional: default 60
+  includeManuallyAdded: false. // optional: default false
+};
+```
+
+```javascript
+AppleHealthKit.getDailyDistanceSwimmingSamples(options, (err: Object, results: Array<Object>) => {
+  if (err) {
+    return;
+  }
+  console.log(results)
+});
+```
diff --git a/docs/getLeanBodyMassSamples().md b/docs/getLeanBodyMassSamples().md
new file mode 100644
index 00000000..93a0af87
--- /dev/null
+++ b/docs/getLeanBodyMassSamples().md
@@ -0,0 +1,28 @@
+Query for lean body mass samples. the options object is used to setup a query to retrieve relevant samples.
+
+```javascript
+let options = {
+  unit: 'pound', // optional; default 'pound'
+  startDate: (new Date(2016,4,27)).toISOString(), // required
+  endDate: (new Date()).toISOString(), // optional; default now
+  ascending: false,	// optional; default false
+  limit:10, // optional; default no limit
+};
+```
+
+```javascript
+AppleHealthKit.getLeanBodyMassSamples(options, (err: Object, results: Array<Object>) => {
+  if (err) {
+    return;
+  }
+  console.log(results)
+});
+```
+
+```javascript
+[
+  { value: 160, startDate: '2016-07-09T00:00:00.000-0400', endDate: '2016-07-10T00:00:00.000-0400' },
+  { value: 161, startDate: '2016-07-08T00:00:00.000-0400', endDate: '2016-07-09T00:00:00.000-0400' },
+  { value: 165, startDate: '2016-07-07T00:00:00.000-0400', endDate: '2016-07-08T00:00:00.000-0400' },
+]
+```
diff --git a/docs/getSamples().md b/docs/getSamples().md
new file mode 100644
index 00000000..a4c6cc68
--- /dev/null
+++ b/docs/getSamples().md
@@ -0,0 +1,52 @@
+Query to get all activities of given type with extended information about it.  
+
+```javascript 1.7
+let options = {
+  startDate: (new Date(2016,4,27)).toISOString(),
+  endDate: (new Date()).toISOString(),
+  type: 'Walking', // one of: ['Walking', 'StairClimbing', 'Running', 'Cycling', 'Workout']
+};
+```
+
+The callback function will be called with a `samples` array containing objects with *value*, *startDate*, and *endDate* fields
+
+```javascript 1.7
+AppleHealthKit.getSamples(options, (err: Object, results: Array<Object>) => {
+  if (err) {
+    return;
+  }
+  console.log(results)
+});
+```
+
+Resulting object has different fields for different types. 
+In case of workout:
+```
+{
+  activityId: Number, // [NSNumber numberWithInt:[sample workoutActivityType]]
+  activityName: Number, // [RCTAppleHealthKit stringForHKWorkoutActivityType:[sample workoutActivityType]]
+  calories: Number, // [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]]
+  tracked: Boolean, // [[sample metadata][HKMetadataKeyWasUserEntered] intValue] !== 1
+  sourceName: String, // [[[sample sourceRevision] source] name]
+  sourceId: String, // [[[sample sourceRevision] source] bundleIdentifier]
+  device: String, // [[sample sourceRevision] productType] or 'iPhone'
+  distance: Number, // [[sample totalDistance] doubleValueForUnit:[HKUnit mileUnit]]
+  start: String, // [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate];
+  end: String, // [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate];
+}
+```
+for other types:
+```
+{
+  tracked: Boolean, // [[sample metadata][HKMetadataKeyWasUserEntered] intValue] !== 1
+  sourceName: String, // [[[sample sourceRevision] source] name]
+  sourceId: String, // [[[sample sourceRevision] source] bundleIdentifier]
+  device: String, // [[sample sourceRevision] productType] or 'iPhone'
+  start: String, // [RCTAppleHealthKit buildISO8601StringFromDate:sample.startDate];
+  end: String, // [RCTAppleHealthKit buildISO8601StringFromDate:sample.endDate];
+  
+  //based on required type, one of the following will be present. 
+  distance: Number, // [[sample totalDistance] doubleValueForUnit:[HKUnit mileUnit]]
+  calories: Number, // [[sample totalEnergyBurned] doubleValueForUnit:[HKUnit kilocalorieUnit]]
+}
+```
diff --git a/docs/saveBodyFatPercentage().md b/docs/saveBodyFatPercentage().md
new file mode 100644
index 00000000..e5f2bc39
--- /dev/null
+++ b/docs/saveBodyFatPercentage().md
@@ -0,0 +1,17 @@
+save a percentage body fat value to Healthkit
+
+`saveBodyFatPercentage` accepts an options object containing a percent value:
+```javascript
+let options = {
+  value: 16.7 // 16.7%
+}
+```
+
+```javascript
+AppleHealthKit.saveBodyFatPercentage(options: Object, (err: Object, results: Object) => {
+  if (err) {
+    return;
+  }
+  // body fat percentage successfully saved
+});
+```
diff --git a/docs/saveLeanBodyMass().md b/docs/saveLeanBodyMass().md
new file mode 100644
index 00000000..44b7a317
--- /dev/null
+++ b/docs/saveLeanBodyMass().md
@@ -0,0 +1,18 @@
+save a numeric lean body mass value to Healthkit
+
+`saveLeanBodyMass` accepts an options object containing a numeric weight value:
+```javascript
+let options = {
+  value: 155.6 // lbs
+}
+```
+
+```javascript
+AppleHealthKit.saveLeanBodyMass(options: Object, (err: Object, results: Object) => {
+    if (err) {
+        console.log("error saving lean body mass to Healthkit: ", err);
+        return;
+    }
+    // Done
+});
+```
diff --git a/docs/setObserver().md b/docs/setObserver().md
new file mode 100644
index 00000000..8f551613
--- /dev/null
+++ b/docs/setObserver().md
@@ -0,0 +1,15 @@
+Will listen for any updates in a given type data in healthKit and call app.
+
+type - one of the `['Walking', 'StairClimbing', 'Running', 'Cycling', 'Workout']`
+```javascript 1.8
+import { NativeAppEventEmitter } from 'react-native';
+//...//
+AppleHealthKit.setObserver({ type: 'Walking' });
+NativeAppEventEmitter.addListener(
+      'observer',
+      callback
+    );
+```
+
+So, callback would be call when new data of given type appears. When it happens, in order to get new info
+need to call getSamples() function with proper arguments. 
diff --git a/package.json b/package.json
index 86205ab3..40bf39af 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "rn-apple-healthkit",
-  "version": "0.6.4",
+  "version": "0.6.5",
   "description": "A React Native package for interacting with Apple HealthKit",
   "main": "index.js",
   "types": "index.d.ts",