"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const bignumber_js_1 = require("bignumber.js");
const contractWrapperFactory_1 = require("../contractWrapperFactory");
const iContractWrapperBase_1 = require("../iContractWrapperBase");
const loggingService_1 = require("../loggingService");
const transactionService_1 = require("../transactionService");
const utils_1 = require("../utils");
const web3EventService_1 = require("../web3EventService");
const mintableToken_1 = require("./mintableToken");
class DaoTokenWrapper
/**
 * In Arc, DAOToken multiply inherits from MintableToken, BurnableToken and ERC827Token.
 * Such a structure not being feasible here, we instead inherit from MintableToken and
 * flatten in the implementations of BurnableToken and ERC827Token.
 */
 extends mintableToken_1.MintableTokenWrapper {
    constructor() {
        super(...arguments);
        this.name = "DAOToken";
        this.friendlyName = "DAO Token";
        this.factory = exports.DaoTokenFactory;
    }
    /**
     * Returns promise of DaoTokenWrapper on the global GEN token.
     */
    static getGenToken() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const address = yield utils_1.Utils.getGenTokenAddress();
            return exports.DaoTokenFactory.at(address);
        });
    }
    /**
     * Mint tokens to recipient
     * @param options
     */
    mint(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!options.recipient) {
                throw new Error("recipient is not defined");
            }
            const amount = new bignumber_js_1.BigNumber(options.amount);
            if (amount.eq(0)) {
                loggingService_1.LoggingService.warn("DaoToken.mint: amount is zero.  Doing nothing.");
                return new iContractWrapperBase_1.ArcTransactionResult(null, this.contract);
            }
            this.logContractFunctionCall("DaoToken.mint", options);
            return this.wrapTransactionInvocation("DaoToken.mint", options, this.contract.mint, [options.recipient, options.amount]);
        });
    }
    /**
     * Burn the given number of tokens
     * @param options
     */
    burn(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const amount = new bignumber_js_1.BigNumber(options.amount);
            if (amount.eq(0)) {
                loggingService_1.LoggingService.warn("DaoToken.burn: amount is zero.  Doing nothing.");
                return new iContractWrapperBase_1.ArcTransactionResult(null, this.contract);
            }
            this.logContractFunctionCall("DaoToken.burn", options);
            return this.wrapTransactionInvocation("DaoToken.burn", options, this.contract.burn, [options.amount]);
        });
    }
    /**
     * Approve transfer of tokens by msg.sender (or `onBehalfOf`, if given)
     * from the given "spender".  Then call the function specified
     * by `callData`, all in a single transaction.
     * @param options
     */
    approveAndCall(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!options.spender) {
                throw new Error("spender is not defined");
            }
            if (!options.callData || !options.callData.length) {
                throw new Error("callData is not defined");
            }
            const amount = new bignumber_js_1.BigNumber(options.amount);
            if (amount.eq(0)) {
                loggingService_1.LoggingService.warn("DaoToken.approveAndCall: amount is zero.  Doing nothing.");
                return new iContractWrapperBase_1.ArcTransactionResult(null, this.contract);
            }
            this.logContractFunctionCall("DaoToken.approveAndCall", options);
            return this.wrapTransactionInvocation("DaoToken.approveAndCall", options, this.contract.approveAndCall, [options.spender, options.amount, options.callData], options.owner ? { from: options.owner } : undefined);
        });
    }
    /**
     * Transfer tokens from the current account to another.  Then call the function specified
     * by `callData`, all in a single transaction.
     * @param options
     */
    transferAndCall(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!options.amount) {
                throw new Error("amount is not defined");
            }
            if (!options.to) {
                throw new Error("to is not defined");
            }
            if (!options.callData || !options.callData.length) {
                throw new Error("callData is not defined");
            }
            const amount = new bignumber_js_1.BigNumber(options.amount);
            if (amount.eq(0)) {
                loggingService_1.LoggingService.warn("DaoToken.transferAndCall: amount is zero.  Doing nothing.");
                return new iContractWrapperBase_1.ArcTransactionResult(null, this.contract);
            }
            this.logContractFunctionCall("DaoToken.transferAndCall", options);
            return this.wrapTransactionInvocation("DaoToken.transferAndCall", options, this.contract.transferAndCall, [options.to, options.amount, options.callData]);
        });
    }
    /**
     * Transfer tokens from one address to another.  Then call the function specified
     * by `callData`, all in a single transaction.
     * @param options
     */
    transferFromAndCall(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!options.amount) {
                throw new Error("amount is not defined");
            }
            if (!options.to) {
                throw new Error("to is not defined");
            }
            if (!options.from) {
                throw new Error("from is not defined");
            }
            if (!options.callData || !options.callData.length) {
                throw new Error("callData is not defined");
            }
            const amount = new bignumber_js_1.BigNumber(options.amount);
            if (amount.eq(0)) {
                loggingService_1.LoggingService.warn("DaoToken.transferFromAndCall: amount is zero.  Doing nothing.");
                return new iContractWrapperBase_1.ArcTransactionResult(null, this.contract);
            }
            this.logContractFunctionCall("DaoToken.transferFromAndCall", options);
            return this.wrapTransactionInvocation("DaoToken.transferFromAndCall", options, this.contract.transferFromAndCall, [options.from, options.to, options.amount, options.callData]);
        });
    }
    /**
     * Increase the number of tokens approved that msg.sender (or `onBehalfOf`, if given)
     * may transfer from the given "spender".
     * Then call the function specified by `callData`, all in a single transaction.
     * @param options
     */
    increaseApprovalAndCall(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!options.spender) {
                throw new Error("spender is not defined");
            }
            if (!options.callData || !options.callData.length) {
                throw new Error("callData is not defined");
            }
            const amount = new bignumber_js_1.BigNumber(options.amount);
            if (amount.eq(0)) {
                loggingService_1.LoggingService.warn("DaoToken.increaseApprovalAndCall: amount is zero.  Doing nothing.");
                return new iContractWrapperBase_1.ArcTransactionResult(null, this.contract);
            }
            this.logContractFunctionCall("DaoToken.increaseApprovalAndCall", options);
            return this.wrapTransactionInvocation("DaoToken.increaseApprovalAndCall", options, this.contract.increaseApprovalAndCall, [options.spender, options.amount, options.callData], options.owner ? { from: options.owner } : undefined);
        });
    }
    /**
     * Decrease the number of tokens approved that msg.sender (or `onBehalfOf` if given)
     * may transfer from the given "spender".
     * Then call the function specified by `callData`, all in a single transaction.
     * @param options
     */
    decreaseApprovalAndCall(options) {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            if (!options.spender) {
                throw new Error("spender is not defined");
            }
            if (!options.callData || !options.callData.length) {
                throw new Error("callData is not defined");
            }
            const amount = new bignumber_js_1.BigNumber(options.amount);
            if (amount.eq(0)) {
                loggingService_1.LoggingService.warn("DaoToken.decreaseApprovalAndCall: amount is zero.  Doing nothing.");
                return new iContractWrapperBase_1.ArcTransactionResult(null, this.contract);
            }
            this.logContractFunctionCall("DaoToken.decreaseApprovalAndCall", options);
            return this.wrapTransactionInvocation("DaoToken.decreaseApprovalAndCallDaoToken.decreaseApprovalAndCall", options, this.contract.decreaseApprovalAndCall, [options.spender, options.amount, options.callData], options.owner ? { from: options.owner } : undefined);
        });
    }
    getTokenName() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.logContractFunctionCall("DaoToken.getTokenName");
            return this.contract.name();
        });
    }
    getTokenSymbol() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.logContractFunctionCall("DaoToken.getTokenSymbol");
            return this.contract.symbol();
        });
    }
    getTokenCap() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            this.logContractFunctionCall("DaoToken.getTokenCap");
            return this.contract.cap();
        });
    }
    approve(options) {
        const _super = name => super[name];
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const functionName = "DaoToken.approve";
            const payload = transactionService_1.TransactionService.publishKickoffEvent(functionName, options, 1);
            const eventContext = transactionService_1.TransactionService.newTxEventContext(functionName, payload, options);
            return _super("approve").call(this, Object.assign(options, { txEventContext: eventContext }));
        });
    }
    transfer(options) {
        const _super = name => super[name];
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const functionName = "DaoToken.transfer";
            const payload = transactionService_1.TransactionService.publishKickoffEvent(functionName, options, 1);
            const eventContext = transactionService_1.TransactionService.newTxEventContext(functionName, payload, options);
            return _super("transfer").call(this, Object.assign(options, { txEventContext: eventContext }));
        });
    }
    transferFrom(options) {
        const _super = name => super[name];
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const functionName = "DaoToken.transferFrom";
            const payload = transactionService_1.TransactionService.publishKickoffEvent(functionName, options, 1);
            const eventContext = transactionService_1.TransactionService.newTxEventContext(functionName, payload, options);
            return _super("transferFrom").call(this, Object.assign(options, { txEventContext: eventContext }));
        });
    }
    increaseApproval(options) {
        const _super = name => super[name];
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const functionName = "DaoToken.increaseApproval";
            const payload = transactionService_1.TransactionService.publishKickoffEvent(functionName, options, 1);
            const eventContext = transactionService_1.TransactionService.newTxEventContext(functionName, payload, options);
            return _super("increaseApproval").call(this, Object.assign(options, { txEventContext: eventContext }));
        });
    }
    finishMinting(options) {
        const _super = name => super[name];
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            const functionName = "DaoToken.finishMinting";
            const payload = transactionService_1.TransactionService.publishKickoffEvent(functionName, options, 1);
            const eventContext = transactionService_1.TransactionService.newTxEventContext(functionName, payload, options);
            return _super("finishMinting").call(this, Object.assign(options, { txEventContext: eventContext }));
        });
    }
    hydrated() {
        super.hydrated();
        /* tslint:disable:max-line-length */
        this.Burn = this.createEventFetcherFactory(this.contract.Burn);
        /* tslint:enable:max-line-length */
    }
}
exports.DaoTokenWrapper = DaoTokenWrapper;
/**
 * defined just to add good type checking
 */
class DaoTokenFactoryType extends contractWrapperFactory_1.ContractWrapperFactory {
    deployed() {
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            throw new Error("DAOToken has not been deployed");
        });
    }
    new(name, symbol, cap) {
        const _super = name => super[name];
        return tslib_1.__awaiter(this, void 0, void 0, function* () {
            return _super("new").call(this, name, symbol, cap);
        });
    }
}
exports.DaoTokenFactoryType = DaoTokenFactoryType;
exports.DaoTokenFactory = new DaoTokenFactoryType("DAOToken", DaoTokenWrapper, new web3EventService_1.Web3EventService());
//# sourceMappingURL=daoToken.js.map