     var date: NSDate { get }
 }
 
-protocol FXResultType {
+// MARK: - Protocol: Transaction Type
+
+protocol FXTransactionType {
     typealias Money: MoneyType
     var money: Money { get }
 
     init(money: Money)
-}
-
-protocol FXExchangeType {
-    typealias RequestType
-
-    /**
-     Exchange money into other money.
-
-     - parameter completion: A completion block which receives
-     the output.
-     */
-    func exchange<M: MoneyType, Result: FXResultType where M.DecimalStorageType == BankersDecimal.DecimalStorageType, M.DecimalStorageType == Result.Money.DecimalStorageType>(money: M, completion: Result -> Void) -> RequestType
 }
 
 /**

//

import Foundation

protocol FXQuoteType {
    var ticker: String { get }

 In addition to FX exchanges, a provide will have its 
 own characteristics, such as a name and fee structure.
*/
protocol FXProviderType {

    typealias RequestType
    typealias QuoteType: FXQuoteType

    /// The name of the provider.
    static var name: String { get }

    static var URLSession: NSURLSession { get }

    static func requestForBaseCurrencyCode(base: String, symbol: String) -> NSURLRequest

    static func exchangeRateFromResponseData(data: NSData) -> Result<QuoteType, FX.Error>
}

// MARK: - MoneyType

extension MoneyType where DecimalStorageType == BankersDecimal.DecimalStorageType {

    func convertWithRate<Other: MoneyType where Other.DecimalStorageType == DecimalStorageType>(rate: BankersDecimal) -> Other {
        return multiplyBy(Other(storage: rate.storage), withBehaviors: Other.DecimalNumberBehavior.decimalNumberBehaviors)
    }

    func exchange<T: FXTransactionType, Provider: FXProviderType where T.Money.DecimalStorageType == DecimalStorageType, Provider.RequestType == NSURLSessionDataTask>(completion: Result<T, FX.Error> -> Void) -> Provider.RequestType {
        let client = FXServiceProviderNetworkClient(session: Provider.URLSession)
        let request = Provider.requestForBaseCurrencyCode(Currency.code, symbol: T.Money.Currency.code)
        return client.get(request, adaptor: Provider.exchangeRateFromResponseData) { result in
            return result.map { T(money: self.convertWithRate($0.rate)) }
        }
    }
}
