diff --git a/commerce.module b/commerce.module
index 63a0716..bd4f5a8 100644
--- a/commerce.module
+++ b/commerce.module
@@ -226,6 +226,30 @@ function commerce_currencies($enabled = FALSE) {
         'fraction_name' => t('Cent'),
         'symbol_placement' => 'before',
       ),
+      'CHF' => array (
+        'numeric_code' => 756,
+        'code' => 'CHF',
+        'name' => t('Swiss franc'),
+        'symbol' => 'CHF',
+        'fraction_name' => t('Rappen'),
+        'symbol_placement' => 'after',
+      ),
+      'GBP' => array (
+        'numeric_code' => 826,
+        'code' => '£',
+        'name' => t('Pound sterling'),
+        'symbol' => 'GBP',
+        'fraction_name' => t('Pence'),
+        'symbol_placement' => 'after',
+      ),
+      'JPY' => array (
+        'numeric_code' => 392,
+        'code' => '¥',
+        'name' => t('Japanese yen'),
+        'symbol' => 'JPY',
+        'fraction_name' => t('Pence'),
+        'symbol_placement' => 'after',
+      ),
     );
 
     // Add default values if they don't exist and convert to objects.
diff --git a/modules/customer/includes/commerce_customer_profile.controller.inc b/modules/customer/includes/commerce_customer_profile.controller.inc
index 808f544..0af4203 100644
--- a/modules/customer/includes/commerce_customer_profile.controller.inc
+++ b/modules/customer/includes/commerce_customer_profile.controller.inc
@@ -50,7 +50,7 @@ class CommerceCustomerProfileEntityController extends DrupalDefaultEntityControl
    *   The saved customer profile object.
    */
   public function save($profile) {
-    $transaction = db_transaction();
+    $transaction = db_transaction('Saves a customer profile');
 
     try {
       global $user;
@@ -214,7 +214,7 @@ class CommerceCustomerProfileEntityController extends DrupalDefaultEntityControl
       // TODO: We'll need to ensure profiles on orders cannot be deleted when we
       // have orders implemented.
 
-      $transaction = db_transaction();
+      $transaction = db_transaction('Delete customer profiles');
 
       try {
         db_delete('commerce_customer_profile')
diff --git a/modules/line_item/includes/commerce_line_item.controller.inc b/modules/line_item/includes/commerce_line_item.controller.inc
index 403a9df..9763ebd 100644
--- a/modules/line_item/includes/commerce_line_item.controller.inc
+++ b/modules/line_item/includes/commerce_line_item.controller.inc
@@ -42,7 +42,7 @@ class CommerceLineItemEntityController extends DrupalDefaultEntityController {
    *   The saved line item object.
    */
   public function save($line_item) {
-    $transaction = db_transaction();
+    $transaction = db_transaction('Saves a line item');
 
     try {
       $line_item->changed = REQUEST_TIME;
@@ -114,7 +114,7 @@ class CommerceLineItemEntityController extends DrupalDefaultEntityController {
     if (!empty($line_item_ids)) {
       $line_items = $this->load($line_item_ids, array());
 
-      $transaction = db_transaction();
+      $transaction = db_transaction('Delete line items');
 
       try {
         db_delete('commerce_line_item')
diff --git a/modules/order/includes/commerce_order.controller.inc b/modules/order/includes/commerce_order.controller.inc
index 9c30bd1..d232c2a 100644
--- a/modules/order/includes/commerce_order.controller.inc
+++ b/modules/order/includes/commerce_order.controller.inc
@@ -51,7 +51,7 @@ class CommerceOrderEntityController extends EntityAPIController {
    *   The saved order object.
    */
   public function save($order) {
-    $transaction = db_transaction();
+    $transaction = db_transaction('Saves an order');
 
     try {
       global $user;
@@ -220,7 +220,7 @@ class CommerceOrderEntityController extends EntityAPIController {
     if (!empty($order_ids)) {
       $orders = $this->load($order_ids, array());
 
-      $transaction = db_transaction();
+      $transaction = db_transaction('Delete orders');
 
       try {
         // Loop through the orders to delete.
diff --git a/modules/product/commerce_product.api.php b/modules/product/commerce_product.api.php
new file mode 100644
index 0000000..9a85652
--- /dev/null
+++ b/modules/product/commerce_product.api.php
@@ -0,0 +1,24 @@
+<?php
+
+/**
+ * @file
+ * This file contains no working PHP code; it exists to provide additional
+ * documentation for doxygen as well as to document hooks in the standard
+ * Drupal manner.
+ */
+
+/**
+ * Declare provided product types.
+ *
+ */
+function hook_commerce_product_info() {
+  $items = array(
+    'product' => array(
+      'type' => t('product'),
+      'name' => t('Product'),
+      'description' => t('A basic product type.'),
+      'help' => '',
+    ),
+  );
+  return $items;
+}
\ No newline at end of file
diff --git a/modules/product/commerce_product.features_api.inc b/modules/product/commerce_product.features_api.inc
new file mode 100644
index 0000000..c0106e7
--- /dev/null
+++ b/modules/product/commerce_product.features_api.inc
@@ -0,0 +1,111 @@
+<?php
+
+/**
+ * Export Drupal Commerce products to Features.
+ */
+
+/**
+ * Product Type export
+ */
+function commerce_product_features_api() {
+  return array(
+  'commerce_product' => array(
+    'name' => t('Commerce Products'),
+    'default_hook' => 'commerce_product_info',
+    'default_file' => FEATURES_DEFAULTS_INCLUDED,
+    'features_source' => TRUE,
+    )
+  );
+}
+
+/**
+ * Implementation of hook_features_export_options().
+ */
+function commerce_product_features_export_options() {
+  $options = array();
+  $product_types = commerce_product_types();
+  if(!empty($product_types)) {
+    foreach($product_types as $type) {
+      $options[$type->type] = $type->name;
+    }
+  }
+  return $options;
+}
+
+function commerce_product_features_export($data, &$export, $module_name = '') {
+  $pipe = array();
+
+  // Add commerce_product as dependency
+  $export['dependencies']['commerce_product'] = 'commerce_product';
+
+  foreach ($data as $type) {
+    $export['features']['commerce_product'][$type] = $type;
+
+    $fields = field_info_instances('commerce_product', $type);
+    foreach ($fields as $name => $field) {
+      $pipe['field'][] = "commerce_product-{$field['bundle']}-{$field['field_name']}";
+    }
+  }
+  return $pipe;
+}
+
+/**
+ * Implementation of hook_features_export_render().
+ */
+function commerce_product_features_export_render($module = 'foo', $data) {
+  $output = array();
+  $output[] = '  $items = array(';
+  foreach ($data as $type) {
+    $info = commerce_product_type_load($type);
+    if(!empty($info)) {
+      $output[] = "  (object) array(";
+      foreach ($info as $key => $t) {
+        if ($t) {
+          $text = str_replace("'", "\'", $info->$key);
+          $text = (!empty($text) && $key !='type') ? "t('{$text}')" : "'{$text}'";
+          $output[] = "      '{$key}' => {$text},";
+        }
+        else {
+          $output[] = "      '{$key}' => '{$info->$key}',";
+        }
+      }
+      $output[] = "    ),";
+    }
+  }
+  $output[] = '  );';
+  $output[] = '  return $items;';
+  $output = implode("\n", $output);
+  return array('commerce_product_info' => $output);
+}
+
+
+/**
+ * Implementation of hook_features_revert().
+ */
+function commerce_product_features_revert($module) {
+  // Get default product types
+  if (module_hook($module, 'commerce_product_info')) {
+    $default_types = module_invoke($module, 'commerce_product_info');
+    foreach ($default_types as $type) {
+      db_delete('commerce_product_type')
+      ->condition('type', $type->type)
+      ->execute();
+    }
+  }
+  else {
+    drupal_set_message(t('Could not load default product types.'), 'error');
+    return FALSE;
+  }
+
+  commerce_product_types_rebuild();
+  menu_rebuild();
+  return TRUE;
+}
+
+
+/**
+ * Implementation of hook_features_rebuild().
+ */
+function commerce_product_features_rebuild($module) {
+  return commerce_product_features_revert($module);
+}
\ No newline at end of file
diff --git a/modules/product/commerce_product.info b/modules/product/commerce_product.info
index 6c62acd..75fd6bb 100644
--- a/modules/product/commerce_product.info
+++ b/modules/product/commerce_product.info
@@ -23,5 +23,8 @@ files[] = includes/views/handlers/commerce_product_handler_field_product_link.in
 files[] = includes/views/handlers/commerce_product_handler_field_product_link_delete.inc
 files[] = includes/views/handlers/commerce_product_handler_field_product_link_edit.inc
 
+; Features API
+files[] = commerce_product.features_api.inc
+
 ; Simple tests
 files[] = tests/commerce_product.test
diff --git a/modules/product/commerce_product.install b/modules/product/commerce_product.install
index a5608ed..139bc00 100644
--- a/modules/product/commerce_product.install
+++ b/modules/product/commerce_product.install
@@ -128,6 +128,13 @@ function commerce_product_schema() {
         'not null' => TRUE,
         'size' => 'medium',
       ),
+      'modified' => array(
+        'description' => 'A boolean indicating whether this type has been modified by an administrator.',
+        'type' => 'int',
+        'not null' => TRUE,
+        'default' => 0,
+        'size' => 'tiny',
+      ),
     ),
     'primary key' => array('type'),
   );
diff --git a/modules/product/commerce_product.module b/modules/product/commerce_product.module
index 26a3456..8942335 100644
--- a/modules/product/commerce_product.module
+++ b/modules/product/commerce_product.module
@@ -170,6 +170,19 @@ function commerce_product_permission() {
 }
 
 /**
+ * Implementation of hook_hook_info().
+ */
+function commerce_product_hook_info() {
+  foreach (array('info') as $hook) {
+    $hooks['commerce_product_' . $hook] = array(
+      'group' => 'commerce_product',
+    );
+  }
+  $hooks['features_api'] = array('group' => 'features_api');
+  return $hooks;
+}
+
+/**
  * Returns an initialized product type object.
  */
 function commerce_product_type_new() {
@@ -178,6 +191,7 @@ function commerce_product_type_new() {
     'name' => '',
     'description' => '',
     'help' => '',
+    'modified' => 0,
   );
 }
 
@@ -203,7 +217,7 @@ function commerce_product_type_save($product_type) {
   menu_rebuild();
 
   // If this is a new product type and the insert did not fail...
-  if (!empty($product_type->is_new) && $op !== FALSE) {
+  if ($op !== FALSE && $op == SAVED_NEW) {
     // Notify the field API that a new bundle has been created.
     field_attach_create_bundle('commerce_product', $product_type->type);
 
@@ -218,6 +232,9 @@ function commerce_product_type_save($product_type) {
     module_invoke_all('commerce_product_type_update', $product_type);
   }
 
+  // Clear the product type cache.
+  drupal_static_reset('_commerce_product_types_build');
+
   return $op;
 }
 
@@ -247,6 +264,9 @@ function commerce_product_type_delete($type) {
   // Rebuild the menu to get rid of this type's product add menu item.
   menu_rebuild();
 
+  // Clear the product type cache.
+  drupal_static_reset('_commerce_product_types_build');
+
   // Notify the field API that this bundle has been destroyed.
   field_attach_delete_bundle('commerce_product', $type);
 
@@ -258,14 +278,94 @@ function commerce_product_type_delete($type) {
  * Returns an array of product type objects keyed by type.
  */
 function commerce_product_types() {
+  return _commerce_product_types_build()->types;
+}
+
+/**
+ * Extract the type name.
+ *
+ * @param $product type
+ *   Either a string or object, containing the product type information.
+ *
+ * @return
+ *   Product type of the passed in data.
+ */
+function _commerce_product_extract_type($type) {
+  return is_object($type) ? $type->type : $type;
+}
+
+/**
+ * Updates the database cache of product types.
+ *
+ * All new module-defined product types are saved to the database via a call to
+ * commerce_product_type_save()
+ *
+ * TODO: Obsolete ones are deleted via a call to commerce_product_type_delete().
+ * Obsolete/Disabled flag will be added in _commerce_product_types_build()
+ */
+function commerce_product_types_rebuild() {
+  // Reset and load updated product types.
+  drupal_static_reset('_commerce_product_types_build');
+
+  foreach (commerce_product_types() as $type) {
+    $existing = commerce_product_type_load($type->type);
+    if (empty($existing)) {
+      $type->is_new = TRUE;
+    }
+    commerce_product_type_save($type);
+  }
+}
+
+/**
+ * Builds and returns the list of available product types similar to the concept used
+ * for node types
+ *
+ * The list of types is built by invoking hook_commerce_product_info() on all modules and
+ * comparing this information with the product types in the {commerce_product_type} table.
+ * These two information sources are not synchronized during module installation
+ * until commerce_product_types_rebuild() is called.
+ *
+ * @return
+ *   Associative array with two components:
+ *   - names: Associative array of the names of product types, keyed by the type.
+ *   - types: Associative array of commerce product type objects, keyed by the type.
+ *   Both of these arrays will include new types that have been defined by
+ *   hook_commerce_product_info() implementations but not yet saved in the {commerce_product_type}
+ *   table.
+ */
+function _commerce_product_types_build() {
   // First check the static cache for a product types array.
   $product_types = &drupal_static(__FUNCTION__);
+  if (is_object($product_types)) {
+    return $product_types;
+  }
+  $product_types = (object)array('types' => array(), 'names' => array());
+
+  // Build product_types from modules that implement commerce_product_info().
+  $module_product_types = module_invoke_all('commerce_product_info');
+  if (count($module_product_types) > 0) {
+    foreach ($module_product_types as $type) {
+      $product_types->types[$type->type] = $type;
+      $product_types->names[$type->type] = $type->name;
+    }
+  }
 
-  // If it did not exist, fetch the types now.
-  if (!isset($product_types)) {
-    $product_types = db_query('SELECT * FROM {commerce_product_type}')->fetchAllAssoc('type');
+  // Get product types from DB and add them to the product types array defined by hook_commerce_product_info()
+  // if they don't exist yet. Product types provided by the hook will override/update product types in the DB.
+  // However, the machine-readable name (type) will stay the same, only metadata is affected.
+  $db_product_types = db_query('SELECT * FROM {commerce_product_type}')->fetchAllAssoc('type');
+  foreach ($db_product_types as $type_object) {
+    // TODO: If product types can be disabled in the future, check for those not used by any module anymore
+    // and mark them as disabled. These product types will then be deleted next time commerce_product_types_rebuild()
+    // is called
+    if (!isset($product_types->types[$type_object->type]) || $type_object->modified) {
+      $product_types->types[$type_object->type] = $type_object;
+      $product_types->names[$type_object->type] = $type_object->name;
+    }
   }
 
+  asort($product_types->names);
+
   return $product_types;
 }
 
@@ -273,8 +373,7 @@ function commerce_product_types() {
  * Resets the cached list of product types.
  */
 function commerce_product_types_reset() {
-  $product_types = &drupal_static('commerce_product_types');
-  $product_types = NULL;
+  drupal_static_reset('commerce_product_types');
 }
 
 /**
@@ -289,25 +388,13 @@ function commerce_product_types_reset() {
  *     type is specified that does not exist, this function returns FALSE.
  */
 function commerce_product_type_get_name($type = NULL) {
-  $product_types = commerce_product_types();
+  $type = _commerce_product_extract_type($type);
+  $types = _commerce_product_types_build()->names;
 
-  // Return a type name if specified and it exists.
-  if (!empty($type)) {
-    if (isset($product_types[$type])) {
-      return $product_types[$type]->name;
-    }
-    else {
-      // Return FALSE if it does not exist.
-      return FALSE;
-    }
-  }
-
-  // Otherwise turn the array values into the type name only.
-  foreach ($product_types as $key => $value) {
-    $product_types[$key] = $value->name;
+  if ($type != NULL && !isset($types[$type])) {
+    return FALSE;
   }
-
-  return $product_types;
+  return isset($types[$type]) ? $types[$type] : $types;
 }
 
 /**
diff --git a/modules/product/includes/commerce_product.controller.inc b/modules/product/includes/commerce_product.controller.inc
index bcbb5d4..5b6f327 100644
--- a/modules/product/includes/commerce_product.controller.inc
+++ b/modules/product/includes/commerce_product.controller.inc
@@ -44,7 +44,7 @@ class CommerceProductEntityController extends DrupalDefaultEntityController {
    *   The saved product object.
    */
   public function save($product) {
-    $transaction = db_transaction();
+    $transaction = db_transaction('Saves a product');
 
     try {
       $product->changed = REQUEST_TIME;
@@ -113,7 +113,7 @@ class CommerceProductEntityController extends DrupalDefaultEntityController {
       // TODO: We'll need to ensure products on orders cannot be deleted when we
       // have orders implemented.
 
-      $transaction = db_transaction();
+      $transaction = db_transaction('Delete products');
 
       try {
         db_delete('commerce_product')
diff --git a/modules/product/includes/commerce_product.forms.inc b/modules/product/includes/commerce_product.forms.inc
index 286308e..3affec9 100644
--- a/modules/product/includes/commerce_product.forms.inc
+++ b/modules/product/includes/commerce_product.forms.inc
@@ -130,8 +130,12 @@ function commerce_product_product_type_form_submit($form, &$form_state) {
 
   // Write the product type to the database.
   $product_type->is_new = !$updated;
+  $product_type->modified = $updated;
   commerce_product_type_save($product_type);
-
+  
+  // Rebuild the product types
+  commerce_product_types_rebuild();
+  
   // Redirect based on the button clicked.
   drupal_set_message(t('Product type saved.'));
 }
@@ -172,6 +176,9 @@ function commerce_product_product_type_delete_form_submit($form, &$form_state) {
 
   commerce_product_type_delete($product_type->type);
 
+  // Rebuild the product types
+  commerce_product_types_rebuild();
+  
   drupal_set_message(t('The product type %name has been deleted.', array('%name' => $product_type->name)));
   watchdog('commerce_product', 'Deleted product type %name.', array('%name' => $product_type->name), WATCHDOG_NOTICE);
 }
