 
 
 @objc public class BRAPIClient: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate, BRAPIAdaptor {
+    // BRAPIClient is intended to be used as a singleton so this is the instance you should use
+    static let sharedClient = BRAPIClient()
+    
+    // whether or not to emit log messages from this instance of the client
     var logEnabled = true
+    
+    // proto is the transport protocol to use for talking to the API (either http or https)
     var proto = "https"
+    
+    // host is the server(s) on which the API is hosted
     var host = "api.breadwallet.com"
     
+    // isFetchingAuth is set to true when a request is currently trying to renew authentication (the token)
+    // it is useful because fetching auth is not idempotent and not reentrant, so at most one auth attempt
+    // can take place at any one time
+    private var isFetchingAuth = false
+    
+    // used when requests are waiting for authentication to be fetched
+    private var authFetchGroup: dispatch_group_t = dispatch_group_create()
+    
+    // storage for the session constructor below
     private var _session: NSURLSession? = nil
-    var session: NSURLSession {
+    
+    // the NSURLSession on which all NSURLSessionTasks are executed
+    private var session: NSURLSession {
         if _session == nil {
             let config = NSURLSessionConfiguration.defaultSessionConfiguration()
             _session = NSURLSession(configuration: config, delegate: self, delegateQueue: queue)
         }
         return _session!
     }
-    var queue = NSOperationQueue()
-    
+    
+    // the queue on which the NSURLSession operates
+    private var queue = NSOperationQueue()
+    
+    // convenience getter for the API endpoint
     var baseUrl: String {
         return "\(proto)://\(host)"
     }
     
-    // the singleton
-    static let sharedClient = BRAPIClient()
-    
+    // prints whatever you give it if logEnabled is true
     func log(s: String) {
         if !logEnabled {
             return

            // add Date header if necessary
            mutableRequest.setValue(NSDate().RFC1123String(), forHTTPHeaderField: "Date")
        }
        if let manager = BRWalletManager.sharedInstance(), tokenData = manager.userAccount,
            token = tokenData["token"], authKey = getAuthKey() {
            let sha = buildRequestSigningString(mutableRequest).dataUsingEncoding(NSUTF8StringEncoding)!.SHA256_2()
            let sig = authKey.compactSign(sha)!.base58String()
            mutableRequest.setValue("bread \(token):\(sig)", forHTTPHeaderField: "Authorization")
        }
        return mutableRequest.copy() as! NSURLRequest
    }

        req.setValue("application/json", forHTTPHeaderField: "Content-Type")
        req.setValue("application/json", forHTTPHeaderField: "Accept")
        let reqJson = [
            "pubKey": authPubKey.base58String(),
            "deviceID": getDeviceId()
        ]
        do {
            let dat = try NSJSONSerialization.dataWithJSONObject(reqJson, options: [])
            req.HTTPBody = dat
        } catch let e {
            log("JSON Serialization error \(e)")
            isFetchingAuth = false
            dispatch_group_leave(authFetchGroup)
            return handler(NSError(domain: BRAPIClientErrorDomain, code: 500, userInfo: [
                NSLocalizedDescriptionKey: NSLocalizedString("JSON Serialization Error", comment: "")]))
        }
        session.dataTaskWithRequest(req) { (data, resp, err) in
            dispatch_async(dispatch_get_main_queue()) {
                if let httpResp = resp as? NSHTTPURLResponse {
                    // unsuccessful response from the server
                    if httpResp.statusCode != 200 {
                        if let data = data, s = String(data: data, encoding: NSUTF8StringEncoding) {
                            self.log("Token error: \(s)")
                        }
                        self.isFetchingAuth = false
                        dispatch_group_leave(self.authFetchGroup)
                        return handler(NSError(domain: BRAPIClientErrorDomain, code: httpResp.statusCode, userInfo: [
                            NSLocalizedDescriptionKey: NSLocalizedString("Unable to retrieve API token", comment: "")]))
                    }
                }
                if let data = data {
                    do {
                        let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
                        self.log("POST /token json response: \(json)")
                        if let topObj = json as? NSDictionary,
                            tok = topObj["token"] as? NSString,
                            uid = topObj["userID"] as? NSString,
                            walletManager = BRWalletManager.sharedInstance() {
                            // success! store it in the keychain
                            let kcData = ["token": tok, "userID": uid]
                            walletManager.userAccount = kcData
                        }
                    } catch let e {
                        self.log("JSON Deserialization error \(e)")
                    }
                }
                self.isFetchingAuth = false
                dispatch_group_leave(self.authFetchGroup)
                handler(err)
            }
        }.resume()
    }
    
    // MARK: URLSession Delegate
