             // 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")
+        if let manager = BRWalletManager.sharedInstance(),
+            tokenData = manager.userAccount,
+            token = tokenData["token"],
+            authKey = getAuthKey(),
+            signingData = buildRequestSigningString(mutableRequest).dataUsingEncoding(NSUTF8StringEncoding),
+            sig = authKey.compactSign(signingData.SHA256_2()) {
+            mutableRequest.setValue("bread \(token):\(sig.base58String())", forHTTPHeaderField: "Authorization")
         }
         return mutableRequest.copy() as! NSURLRequest
     }



@objc public class BRAPIClient: NSObject, NSURLSessionDelegate, NSURLSessionTaskDelegate, BRAPIAdaptor {
    var logEnabled = true
    var proto = "https"
    var host = "api.breadwallet.com"
    
    private var _session: NSURLSession? = nil
    var session: NSURLSession {
        if _session == nil {
            let config = NSURLSessionConfiguration.defaultSessionConfiguration()
            _session = NSURLSession(configuration: config, delegate: self, delegateQueue: queue)
        }
        return _session!
    }
    var queue = NSOperationQueue()
    
    var baseUrl: String {
        return "\(proto)://\(host)"
    }
    
    // the singleton
    static let sharedClient = BRAPIClient()
    
    func log(s: String) {
        if !logEnabled {
            return

        }
        let origRequest = request.mutableCopy() as! NSURLRequest
        var actualRequest = request
        if authenticated {
            actualRequest = signRequest(request)
        }
        return session.dataTaskWithRequest(actualRequest) { (data, resp, err) -> Void in
            dispatch_async(dispatch_get_main_queue()) {
                let end = NSDate()
                let dur = Int(end.timeIntervalSinceDate(start) * 1000)
                if let httpResp = resp as? NSHTTPURLResponse {
                    var errStr = ""
                    if httpResp.statusCode >= 400 {
                        if let data = data, s = NSString(data: data, encoding: NSUTF8StringEncoding) {
                            errStr = s as String
                        }
                    }
                    
                    self.log("\(logLine) -> status=\(httpResp.statusCode) duration=\(dur)ms errStr=\(errStr)")
                    
                    if authenticated && isBreadChallenge(httpResp) {
                        self.log("\(logLine) got authentication challenge from API - will attempt to get token")
                        self.getToken { err in
                            if err != nil && retryCount < 1 { // retry once
                                self.log("\(logLine) error retrieving token: \(err) - will retry")
                                dispatch_after(1, dispatch_get_main_queue()) {
                                    self.dataTaskWithRequest(
                                        origRequest, authenticated: authenticated,
                                        retryCount: retryCount + 1, handler: handler
                                        ).resume()
                                }
                            } else if err != nil && retryCount > 0 { // fail if we already retried
                                self.log("\(logLine) error retrieving token: \(err) - will no longer retry")
                                handler(nil, nil, err)
                            } else if retryCount < 1 { // no error, so attempt the request again
                                self.log("\(logLine) retrieved token, so retrying the original request")
                                self.dataTaskWithRequest(
                                    origRequest, authenticated: authenticated,
                                    retryCount: retryCount + 1, handler: handler).resume()
                            } else {
                                self.log("\(logLine) retried token multiple times, will not retry again")
                                handler(data, httpResp, err)
                            }
                        }
                    } else {
                        handler(data, httpResp, err)
                    }
                } else {
                    self.log("\(logLine) encountered connection error \(err)")
                    handler(data, nil, err)
                }
            }
        }
    }
    
    // retrieve a token and save it in the keychain data for this account
    func getToken(handler: (NSError?) -> Void) {
        if isFetchingAuth {
            log("already fetching auth, waiting...")
            dispatch_group_notify(authFetchGroup, dispatch_get_main_queue()) {
                handler(nil)
            }
            return
        }
        isFetchingAuth = true
        log("auth: entering group")
        dispatch_group_enter(authFetchGroup)
        guard let authKey = getAuthKey(), authPubKey = authKey.publicKey else {
            return handler(NSError(domain: BRAPIClientErrorDomain, code: 500, userInfo: [
                NSLocalizedDescriptionKey: NSLocalizedString("Wallet not ready", comment: "")]))
        }
