Source: composer-runtime/lib/engine.transactions.js

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

const Logger = require('composer-common').Logger;
const util = require('util');

const LOG = Logger.getLog('EngineTransactions');

/**
 * The JavaScript engine responsible for processing chaincode commands.
 * @protected
 * @memberof module:composer-runtime
 */
class EngineTransactions {

    /**
     * Submit a transaction for execution.
     * @param {Context} context The request context.
     * @param {string[]} args The arguments to pass to the chaincode function.
     * @return {Promise} A promise that will be resolved when complete, or rejected
     * with an error.
     */
    submitTransaction(context, args) {
        const method = 'submitTransaction';
        LOG.entry(method, context, args);
        if (args.length !== 2) {
            LOG.error(method, 'Invalid arguments', args);
            throw new Error(util.format('Invalid arguments "%j" to function "%s", expecting "%j"', args, 'submitTransaction', ['registryId', 'serializedResource']));
        }

        // Find the default transaction registry.
        let registryManager = context.getRegistryManager();
        let transaction = null, resolvedTransaction = null;

        // Parse the transaction from the JSON string..
        LOG.debug(method, 'Parsing transaction from JSON');
        let transactionData = JSON.parse(args[1]);

        // Now we need to convert the JavaScript object into a transaction resource.
        LOG.debug(method, 'Parsing transaction from parsed JSON object');
        // First we parse *our* copy, that is not resolved. This is the copy that gets added to the
        // transaction registry, and is the one in the context (for adding log entries).
        transaction = context.getSerializer().fromJSON(transactionData);
        // Then we parse the *users* copy, that is resolved, and they can modify to their hearts content.
        // This is only given to the user, and is discarded afterwards.
        resolvedTransaction = context.getSerializer().fromJSON(transactionData);

        // Store the transaction in the context.
        context.setTransaction(transaction);

        // Resolve the users copy of the transaction.
        LOG.debug(method, 'Parsed transaction, resolving it', resolvedTransaction);
        return context.getResolver().resolve(resolvedTransaction)
            .then(() => {

                // Get the list of transaction executors.
                let transactionExecutors = context.getTransactionExecutors();
                let api = context.getApi();
                let scriptManager = context.getScriptManager();

                // Let each one process the transaction in turn.
                return transactionExecutors.reduce((result, transactionExecutor) => {
                    return result.then(() => {
                        LOG.debug(method, 'Calling transaction executor', transactionExecutor.getType());
                        return transactionExecutor.execute(api, scriptManager, transaction, resolvedTransaction);
                    });
                }, Promise.resolve());

            })
            .then(() => {

                // Get the default transaction registry.
                LOG.debug(method, 'Getting default transaction registry');
                return registryManager.get('Transaction', 'default');

            })
            .then((transactionRegistry) => {

                // Store the transaction in the transaction registry.
                LOG.debug(method, 'Storing executed transaction in transaction registry');
                return transactionRegistry.add(transaction);

            });

    }

}

module.exports = EngineTransactions;