'use strict';Object.defineProperty(exports, "__esModule", { value: true });exports.default = undefined;var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();var _createClass = function () {function defineProperties(target, props) {for (var i = 0; i < props.length; i++) {var descriptor = props[i];descriptor.enumerable = descriptor.enumerable || false;descriptor.configurable = true;if ("value" in descriptor) descriptor.writable = true;Object.defineProperty(target, descriptor.key, descriptor);}}return function (Constructor, protoProps, staticProps) {if (protoProps) defineProperties(Constructor.prototype, protoProps);if (staticProps) defineProperties(Constructor, staticProps);return Constructor;};}(); // Copyright 2015-2017 Parity Technologies (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity.  If not, see <http://www.gnu.org/licenses/>.

var _bignumber = require('bignumber.js');var _bignumber2 = _interopRequireDefault(_bignumber);

var _abi = require('@parity/abi');var _abi2 = _interopRequireDefault(_abi);
var _contract = require('@parity/api/lib/contract');var _contract2 = _interopRequireDefault(_contract);
var _format = require('@parity/api/lib/util/format');

var _consensysMultisigWallet = require('../../contracts/abi/consensys-multisig-wallet.json');var _consensysMultisigWallet2 = _interopRequireDefault(_consensysMultisigWallet);

var _updates = require('./updates');function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}function _defineProperty(obj, key, value) {if (key in obj) {Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true });} else {obj[key] = value;}return obj;}function _classCallCheck(instance, Constructor) {if (!(instance instanceof Constructor)) {throw new TypeError("Cannot call a class as a function");}}

var WALLET_CONTRACT = new _contract2.default({}, _consensysMultisigWallet2.default);
var WALLET_ABI = new _abi2.default(_consensysMultisigWallet2.default);

var walletEvents = WALLET_ABI.events.reduce(function (events, event) {
  events[event.name] = event;
  return events;
}, {});

var WalletSignatures = {
  Confirmation: (0, _format.toHex)(walletEvents.Confirmation.signature),
  Revocation: (0, _format.toHex)(walletEvents.Revocation.signature),
  Deposit: (0, _format.toHex)(walletEvents.Deposit.signature),
  Execution: (0, _format.toHex)(walletEvents.Execution.signature),
  OwnerAddition: (0, _format.toHex)(walletEvents.OwnerAddition.signature),
  OwnerRemoval: (0, _format.toHex)(walletEvents.OwnerRemoval.signature),
  RequirementChange: (0, _format.toHex)(walletEvents.RequirementChange.signature),
  Submission: (0, _format.toHex)(walletEvents.Submission.signature) };var


ConsensysWalletUtils = function () {function ConsensysWalletUtils() {_classCallCheck(this, ConsensysWalletUtils);}_createClass(ConsensysWalletUtils, null, [{ key: 'fetchOwners', value: function fetchOwners(
    inWallet) {
      var wallet = new _contract2.default(inWallet.api, _consensysMultisigWallet2.default).at(inWallet.address);

      return wallet.instance.getOwners.call().
      then(function (owners) {
        return owners.map(function (token) {return token.value;});
      });
    } }, { key: 'fetchPendingTransactions', value: function fetchPendingTransactions(

    inWallet) {
      var wallet = new _contract2.default(inWallet.api, _consensysMultisigWallet2.default).at(inWallet.address);

      var transactions = void 0;
      var txIds = void 0;

      // Get pending and not exectued transactions
      return wallet.instance.getTransactionCount.
      call({}, [true, false]).
      then(function (txCount) {
        // Get all the pending transactions
        var fromId = 0;
        var toId = txCount;

        return wallet.instance.getTransactionIds.
        call({}, [fromId, toId, true, false]);
      }).
      then(function (_txIds) {
        txIds = _txIds.map(function (token) {return token.value;});

        var promises = txIds.map(function (txId) {
          return wallet.instance.transactions.
          call({}, [txId]);
        });

        return Promise.all(promises);
      }).
      then(function (transactions) {
        return transactions.map(function (transaction, index) {var _transaction = _slicedToArray(
          transaction, 3),destination = _transaction[0],value = _transaction[1],data = _transaction[2];
          var id = (0, _format.toHex)(txIds[index]);

          return {
            to: destination,
            data: data,
            value: value,
            operation: id };

        });
      }).
      then(function (_transactions) {
        transactions = _transactions;

        return wallet.
        getAllLogs({
          topics: [
          WalletSignatures.Submission,
          txIds.map(function (txId) {return (0, _format.toHex)(txId);})] });


      }).
      then(function (logs) {
        transactions.forEach(function (tx) {
          var log = logs.
          find(function (log) {
            var id = (0, _format.toHex)(log.params.transactionId.value);

            return id === tx.operation;
          });

          if (!log) {
            console.warn('could not find a Submission log for this operation', tx);
            return;
          }

          tx.transactionIndex = log.transactionIndex;
          tx.transactionHash = log.transactionHash;
          tx.blockNumber = log.blockNumber;
        });

        var confirmationsPromises = transactions.map(function (tx) {
          return wallet.instance.getConfirmations.
          call({}, [tx.operation]).
          then(function (owners) {
            return owners.map(function (token) {return token.value;});
          });
        });

        return Promise.all(confirmationsPromises);
      }).
      then(function (confirmations) {
        transactions.forEach(function (tx, index) {
          tx.confirmedBy = confirmations[index];
        });

        return transactions;
      });
    } }, { key: 'fetchRequire', value: function fetchRequire(

    inWallet) {
      var wallet = new _contract2.default(inWallet.api, _consensysMultisigWallet2.default).at(inWallet.address);

      return wallet.instance.required.call();
    } }, { key: 'fetchTransactions', value: function fetchTransactions(

    inWallet) {
      var wallet = new _contract2.default(inWallet.api, _consensysMultisigWallet2.default).at(inWallet.address);

      var transactions = void 0;
      var txIds = void 0;

      return wallet.instance.getTransactionCount.
      call({}, [false, true]).
      then(function (txCount) {
        // Get the 20 last transactions
        var fromId = Math.max(0, txCount - 20);
        var toId = txCount;

        return wallet.instance.getTransactionIds.
        call({}, [fromId, toId, false, true]);
      }).
      then(function (_txIds) {
        txIds = _txIds.map(function (token) {return token.value;});

        var promises = txIds.map(function (txId) {
          return wallet.instance.transactions.
          call({}, [txId]);
        });

        return Promise.all(promises);
      }).
      then(function (transactions) {
        return transactions.map(function (transaction, index) {var _transaction2 = _slicedToArray(
          transaction, 4),destination = _transaction2[0],value = _transaction2[1],data = _transaction2[2],executed = _transaction2[3];
          var id = (0, _format.toHex)(txIds[index]);

          return {
            destination: destination, value: value, data: data, executed: executed, id: id };

        });
      }).
      then(function (_transactions) {
        transactions = _transactions;

        var depositLogs = wallet.
        getAllLogs({
          topics: [WalletSignatures.Deposit] });


        var executionLogs = wallet.
        getAllLogs({
          topics: [WalletSignatures.Execution, txIds] });


        return Promise.all([depositLogs, executionLogs]);
      }).
      then(function (_ref) {var _ref2 = _slicedToArray(_ref, 2),depositLogs = _ref2[0],executionLogs = _ref2[1];
        var logs = [].concat(depositLogs, executionLogs);

        return logs.map(function (log) {
          var signature = (0, _format.toHex)(log.topics[0]);

          var transaction = {
            transactionHash: log.transactionHash,
            transactionIndex: log.transactionIndex,
            blockNumber: log.blockNumber };


          if (signature === WalletSignatures.Deposit) {
            transaction.from = log.params.sender.value;
            transaction.value = log.params.value.value;
            transaction.to = wallet.address;
          } else {
            var txId = (0, _format.toHex)(log.params.transactionId.value);
            var tx = transactions.find(function (tx) {return tx.id === txId;});

            transaction.from = wallet.address;
            transaction.to = tx.destination;
            transaction.value = tx.value;
            transaction.data = tx.data;
            transaction.operation = (0, _format.toHex)(tx.id);
          }

          return transaction;
        });
      });
    } }, { key: 'getChangeMethod', value: function getChangeMethod(

    api, address, change) {
      var wallet = new _contract2.default(api, _consensysMultisigWallet2.default).at(address);
      var walletInstance = wallet.instance;

      var data = '';

      if (change.type === 'require') {
        var func = walletInstance.changeRequirement;

        data = wallet.getCallData(func, {}, [change.value]);
      }

      if (change.type === 'add_owner') {
        var _func = walletInstance.addOwner;

        data = wallet.getCallData(_func, {}, [change.value]);
      }

      if (change.type === 'change_owner') {
        var _func2 = walletInstance.replaceOwner;

        data = wallet.getCallData(_func2, {}, [change.value.from, change.value.to]);
      }

      if (change.type === 'remove_owner') {
        var _func3 = walletInstance.removeOwner;

        data = wallet.getCallData(_func3, {}, [change.value]);
      }

      var method = walletInstance.submitTransaction;
      var values = [address, 0, data];

      return { method: method, values: values };
    } }, { key: 'getModifyOperationMethod', value: function getModifyOperationMethod(

    modification) {
      switch (modification) {
        case 'confirm':
          return 'confirmTransaction';

        case 'revoke':
          return 'revokeConfirmation';

        default:
          return '';}

    } }, { key: 'getSubmitMethod', value: function getSubmitMethod()

    {
      return 'submitTransaction';
    } }, { key: 'getWalletContract', value: function getWalletContract(

    api) {
      return new _contract2.default(api, _consensysMultisigWallet2.default);
    } }, { key: 'getWalletSignatures', value: function getWalletSignatures()

    {
      return WalletSignatures;
    } }, { key: 'fetchDailylimit', value: function fetchDailylimit()

    {
      return {
        last: new _bignumber2.default(0),
        limit: new _bignumber2.default(0),
        spent: new _bignumber2.default(0) };

    } }, { key: 'isWallet', value: function isWallet(

    api, address) {
      var wallet = new _contract2.default(api, _consensysMultisigWallet2.default).at(address);

      return ConsensysWalletUtils.fetchRequire(wallet).
      then(function (result) {
        if (!result || result.equals(0)) {
          return false;
        }

        return true;
      });
    } }, { key: 'logToUpdate', value: function logToUpdate(

    log) {
      var eventSignature = (0, _format.toHex)(log.topics[0]);

      switch (eventSignature) {
        case WalletSignatures.OwnerAddition:
        case WalletSignatures.OwnerRemoval:
          return _defineProperty({}, _updates.UPDATE_OWNERS, true);

        case WalletSignatures.RequirementChange:
          return _defineProperty({}, _updates.UPDATE_REQUIRE, true);

        case WalletSignatures.Deposit:
        case WalletSignatures.Execution:
          return _defineProperty({}, _updates.UPDATE_TRANSACTIONS, true);

        case WalletSignatures.Submission:
        case WalletSignatures.Confirmation:
        case WalletSignatures.Revocation:
          var parsedLog = WALLET_CONTRACT.parseEventLogs([log])[0];
          var operation = (0, _format.toHex)(parsedLog.params.transactionId.value);

          return _defineProperty({}, _updates.UPDATE_CONFIRMATIONS, operation);

        default:
          return {};}

    }

    /**
       * This type of wallet cannot create any contract...
       */ }, { key: 'parseTransactionLogs', value: function parseTransactionLogs(
    api, options, rawLogs) {
      return null;
    } }]);return ConsensysWalletUtils;}();exports.default = ConsensysWalletUtils;