// tslint:disable:no-consecutive-blank-lines ordered-imports align trailing-comma enum-naming
// tslint:disable:whitespace no-unbound-method no-trailing-whitespace
// tslint:disable:no-unused-variable
import {
    AwaitTransactionSuccessOpts,
    ContractFunctionObj,
    ContractTxFunctionObj,
    SendTransactionOpts,
    BaseContract,
    SubscriptionManager,
    PromiseWithTransactionHash,
    methodAbiToFunctionSignature,
} from '@0x/base-contract';
import { schemas } from '@0x/json-schemas';
import {
    BlockParam,
    BlockParamLiteral,
    BlockRange,
    CallData,
    ContractAbi,
    ContractArtifact,
    DecodedLogArgs,
    LogWithDecodedArgs,
    MethodAbi,
    TransactionReceiptWithDecodedLogs,
    TxData,
    TxDataPayable,
    SupportedProvider,
} from 'ethereum-types';
import { BigNumber, classUtils, logUtils, providerUtils } from '@0x/utils';
import { EventCallback, IndexedFilterValues, SimpleContractArtifact } from '@0x/types';
import { Web3Wrapper } from '@0x/web3-wrapper';
import { assert } from '@0x/assert';
import * as ethers from 'ethers';
// tslint:enable:no-unused-variable

export type StakingEventArgs =
    | StakingAuthorizedAddressAddedEventArgs
    | StakingAuthorizedAddressRemovedEventArgs
    | StakingEpochEndedEventArgs
    | StakingEpochFinalizedEventArgs
    | StakingExchangeAddedEventArgs
    | StakingExchangeRemovedEventArgs
    | StakingMakerStakingPoolSetEventArgs
    | StakingMoveStakeEventArgs
    | StakingOperatorShareDecreasedEventArgs
    | StakingOwnershipTransferredEventArgs
    | StakingParamsSetEventArgs
    | StakingRewardsPaidEventArgs
    | StakingStakeEventArgs
    | StakingStakingPoolCreatedEventArgs
    | StakingStakingPoolEarnedRewardsInEpochEventArgs
    | StakingUnstakeEventArgs;

export enum StakingEvents {
    AuthorizedAddressAdded = 'AuthorizedAddressAdded',
    AuthorizedAddressRemoved = 'AuthorizedAddressRemoved',
    EpochEnded = 'EpochEnded',
    EpochFinalized = 'EpochFinalized',
    ExchangeAdded = 'ExchangeAdded',
    ExchangeRemoved = 'ExchangeRemoved',
    MakerStakingPoolSet = 'MakerStakingPoolSet',
    MoveStake = 'MoveStake',
    OperatorShareDecreased = 'OperatorShareDecreased',
    OwnershipTransferred = 'OwnershipTransferred',
    ParamsSet = 'ParamsSet',
    RewardsPaid = 'RewardsPaid',
    Stake = 'Stake',
    StakingPoolCreated = 'StakingPoolCreated',
    StakingPoolEarnedRewardsInEpoch = 'StakingPoolEarnedRewardsInEpoch',
    Unstake = 'Unstake',
}

export interface StakingAuthorizedAddressAddedEventArgs extends DecodedLogArgs {
    target: string;
    caller: string;
}

export interface StakingAuthorizedAddressRemovedEventArgs extends DecodedLogArgs {
    target: string;
    caller: string;
}

export interface StakingEpochEndedEventArgs extends DecodedLogArgs {
    epoch: BigNumber;
    numPoolsToFinalize: BigNumber;
    rewardsAvailable: BigNumber;
    totalFeesCollected: BigNumber;
    totalWeightedStake: BigNumber;
}

export interface StakingEpochFinalizedEventArgs extends DecodedLogArgs {
    epoch: BigNumber;
    rewardsPaid: BigNumber;
    rewardsRemaining: BigNumber;
}

export interface StakingExchangeAddedEventArgs extends DecodedLogArgs {
    exchangeAddress: string;
}

export interface StakingExchangeRemovedEventArgs extends DecodedLogArgs {
    exchangeAddress: string;
}

export interface StakingMakerStakingPoolSetEventArgs extends DecodedLogArgs {
    makerAddress: string;
    poolId: string;
}

export interface StakingMoveStakeEventArgs extends DecodedLogArgs {
    staker: string;
    amount: BigNumber;
    fromStatus: number;
    fromPool: string;
    toStatus: number;
    toPool: string;
}

export interface StakingOperatorShareDecreasedEventArgs extends DecodedLogArgs {
    poolId: string;
    oldOperatorShare: number;
    newOperatorShare: number;
}

export interface StakingOwnershipTransferredEventArgs extends DecodedLogArgs {
    previousOwner: string;
    newOwner: string;
}

export interface StakingParamsSetEventArgs extends DecodedLogArgs {
    epochDurationInSeconds: BigNumber;
    rewardDelegatedStakeWeight: number;
    minimumPoolStake: BigNumber;
    cobbDouglasAlphaNumerator: BigNumber;
    cobbDouglasAlphaDenominator: BigNumber;
}

export interface StakingRewardsPaidEventArgs extends DecodedLogArgs {
    epoch: BigNumber;
    poolId: string;
    operatorReward: BigNumber;
    membersReward: BigNumber;
}

export interface StakingStakeEventArgs extends DecodedLogArgs {
    staker: string;
    amount: BigNumber;
}

export interface StakingStakingPoolCreatedEventArgs extends DecodedLogArgs {
    poolId: string;
    operator: string;
    operatorShare: number;
}

export interface StakingStakingPoolEarnedRewardsInEpochEventArgs extends DecodedLogArgs {
    epoch: BigNumber;
    poolId: string;
}

export interface StakingUnstakeEventArgs extends DecodedLogArgs {
    staker: string;
    amount: BigNumber;
}

/* istanbul ignore next */
// tslint:disable:no-parameter-reassignment
// tslint:disable-next-line:class-name
export class StakingContract extends BaseContract {
    /**
     * @ignore
     */
    public static deployedBytecode: string | undefined;
    private readonly _methodABIIndex: { [name: string]: number } = {};
    private readonly _subscriptionManager: SubscriptionManager<StakingEventArgs, StakingEvents>;
    public static async deployFrom0xArtifactAsync(
        artifact: ContractArtifact | SimpleContractArtifact,
        supportedProvider: SupportedProvider,
        txDefaults: Partial<TxData>,
        logDecodeDependencies: { [contractName: string]: ContractArtifact | SimpleContractArtifact },
        wethAddress: string,
        zrxVaultAddress: string,
    ): Promise<StakingContract> {
        assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
            schemas.addressSchema,
            schemas.numberSchema,
            schemas.jsNumber,
        ]);
        if (artifact.compilerOutput === undefined) {
            throw new Error('Compiler output not found in the artifact file');
        }
        const provider = providerUtils.standardizeOrThrow(supportedProvider);
        const bytecode = artifact.compilerOutput.evm.bytecode.object;
        const abi = artifact.compilerOutput.abi;
        const logDecodeDependenciesAbiOnly: { [contractName: string]: ContractAbi } = {};
        if (Object.keys(logDecodeDependencies) !== undefined) {
            for (const key of Object.keys(logDecodeDependencies)) {
                logDecodeDependenciesAbiOnly[key] = logDecodeDependencies[key].compilerOutput.abi;
            }
        }
        return StakingContract.deployAsync(
            bytecode,
            abi,
            provider,
            txDefaults,
            logDecodeDependenciesAbiOnly,
            wethAddress,
            zrxVaultAddress,
        );
    }
    public static async deployAsync(
        bytecode: string,
        abi: ContractAbi,
        supportedProvider: SupportedProvider,
        txDefaults: Partial<TxData>,
        logDecodeDependencies: { [contractName: string]: ContractAbi },
        wethAddress: string,
        zrxVaultAddress: string,
    ): Promise<StakingContract> {
        assert.isHexString('bytecode', bytecode);
        assert.doesConformToSchema('txDefaults', txDefaults, schemas.txDataSchema, [
            schemas.addressSchema,
            schemas.numberSchema,
            schemas.jsNumber,
        ]);
        const provider = providerUtils.standardizeOrThrow(supportedProvider);
        const constructorAbi = BaseContract._lookupConstructorAbi(abi);
        [wethAddress, zrxVaultAddress] = BaseContract._formatABIDataItemList(
            constructorAbi.inputs,
            [wethAddress, zrxVaultAddress],
            BaseContract._bigNumberToString,
        );
        const iface = new ethers.utils.Interface(abi);
        const deployInfo = iface.deployFunction;
        const txData = deployInfo.encode(bytecode, [wethAddress, zrxVaultAddress]);
        const web3Wrapper = new Web3Wrapper(provider);
        const txDataWithDefaults = await BaseContract._applyDefaultsToContractTxDataAsync(
            {
                data: txData,
                ...txDefaults,
            },
            web3Wrapper.estimateGasAsync.bind(web3Wrapper),
        );
        const txHash = await web3Wrapper.sendTransactionAsync(txDataWithDefaults);
        logUtils.log(`transactionHash: ${txHash}`);
        const txReceipt = await web3Wrapper.awaitTransactionSuccessAsync(txHash);
        logUtils.log(`Staking successfully deployed at ${txReceipt.contractAddress}`);
        const contractInstance = new StakingContract(
            txReceipt.contractAddress as string,
            provider,
            txDefaults,
            logDecodeDependencies,
        );
        contractInstance.constructorArgs = [wethAddress, zrxVaultAddress];
        return contractInstance;
    }

    /**
     * @returns      The contract ABI
     */
    public static ABI(): ContractAbi {
        const abi = [
            {
                inputs: [
                    {
                        name: 'wethAddress',
                        type: 'address',
                    },
                    {
                        name: 'zrxVaultAddress',
                        type: 'address',
                    },
                ],
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'constructor',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'target',
                        type: 'address',
                        indexed: true,
                    },
                    {
                        name: 'caller',
                        type: 'address',
                        indexed: true,
                    },
                ],
                name: 'AuthorizedAddressAdded',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'target',
                        type: 'address',
                        indexed: true,
                    },
                    {
                        name: 'caller',
                        type: 'address',
                        indexed: true,
                    },
                ],
                name: 'AuthorizedAddressRemoved',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'epoch',
                        type: 'uint256',
                        indexed: true,
                    },
                    {
                        name: 'numPoolsToFinalize',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'rewardsAvailable',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'totalFeesCollected',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'totalWeightedStake',
                        type: 'uint256',
                        indexed: false,
                    },
                ],
                name: 'EpochEnded',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'epoch',
                        type: 'uint256',
                        indexed: true,
                    },
                    {
                        name: 'rewardsPaid',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'rewardsRemaining',
                        type: 'uint256',
                        indexed: false,
                    },
                ],
                name: 'EpochFinalized',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'exchangeAddress',
                        type: 'address',
                        indexed: false,
                    },
                ],
                name: 'ExchangeAdded',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'exchangeAddress',
                        type: 'address',
                        indexed: false,
                    },
                ],
                name: 'ExchangeRemoved',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'makerAddress',
                        type: 'address',
                        indexed: true,
                    },
                    {
                        name: 'poolId',
                        type: 'bytes32',
                        indexed: true,
                    },
                ],
                name: 'MakerStakingPoolSet',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'staker',
                        type: 'address',
                        indexed: true,
                    },
                    {
                        name: 'amount',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'fromStatus',
                        type: 'uint8',
                        indexed: false,
                    },
                    {
                        name: 'fromPool',
                        type: 'bytes32',
                        indexed: true,
                    },
                    {
                        name: 'toStatus',
                        type: 'uint8',
                        indexed: false,
                    },
                    {
                        name: 'toPool',
                        type: 'bytes32',
                        indexed: true,
                    },
                ],
                name: 'MoveStake',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                        indexed: true,
                    },
                    {
                        name: 'oldOperatorShare',
                        type: 'uint32',
                        indexed: false,
                    },
                    {
                        name: 'newOperatorShare',
                        type: 'uint32',
                        indexed: false,
                    },
                ],
                name: 'OperatorShareDecreased',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'previousOwner',
                        type: 'address',
                        indexed: true,
                    },
                    {
                        name: 'newOwner',
                        type: 'address',
                        indexed: true,
                    },
                ],
                name: 'OwnershipTransferred',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'epochDurationInSeconds',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'rewardDelegatedStakeWeight',
                        type: 'uint32',
                        indexed: false,
                    },
                    {
                        name: 'minimumPoolStake',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'cobbDouglasAlphaNumerator',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'cobbDouglasAlphaDenominator',
                        type: 'uint256',
                        indexed: false,
                    },
                ],
                name: 'ParamsSet',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'epoch',
                        type: 'uint256',
                        indexed: true,
                    },
                    {
                        name: 'poolId',
                        type: 'bytes32',
                        indexed: true,
                    },
                    {
                        name: 'operatorReward',
                        type: 'uint256',
                        indexed: false,
                    },
                    {
                        name: 'membersReward',
                        type: 'uint256',
                        indexed: false,
                    },
                ],
                name: 'RewardsPaid',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'staker',
                        type: 'address',
                        indexed: true,
                    },
                    {
                        name: 'amount',
                        type: 'uint256',
                        indexed: false,
                    },
                ],
                name: 'Stake',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                        indexed: false,
                    },
                    {
                        name: 'operator',
                        type: 'address',
                        indexed: false,
                    },
                    {
                        name: 'operatorShare',
                        type: 'uint32',
                        indexed: false,
                    },
                ],
                name: 'StakingPoolCreated',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'epoch',
                        type: 'uint256',
                        indexed: true,
                    },
                    {
                        name: 'poolId',
                        type: 'bytes32',
                        indexed: true,
                    },
                ],
                name: 'StakingPoolEarnedRewardsInEpoch',
                outputs: [],
                type: 'event',
            },
            {
                anonymous: false,
                inputs: [
                    {
                        name: 'staker',
                        type: 'address',
                        indexed: true,
                    },
                    {
                        name: 'amount',
                        type: 'uint256',
                        indexed: false,
                    },
                ],
                name: 'Unstake',
                outputs: [],
                type: 'event',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'target',
                        type: 'address',
                    },
                ],
                name: 'addAuthorizedAddress',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'addr',
                        type: 'address',
                    },
                ],
                name: 'addExchangeAddress',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'index_0',
                        type: 'uint256',
                    },
                ],
                name: 'aggregatedStatsByEpoch',
                outputs: [
                    {
                        name: 'rewardsAvailable',
                        type: 'uint256',
                    },
                    {
                        name: 'numPoolsToFinalize',
                        type: 'uint256',
                    },
                    {
                        name: 'totalFeesCollected',
                        type: 'uint256',
                    },
                    {
                        name: 'totalWeightedStake',
                        type: 'uint256',
                    },
                    {
                        name: 'totalRewardsFinalized',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'index_0',
                        type: 'uint256',
                    },
                ],
                name: 'authorities',
                outputs: [
                    {
                        name: '',
                        type: 'address',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'index_0',
                        type: 'address',
                    },
                ],
                name: 'authorized',
                outputs: [
                    {
                        name: '',
                        type: 'bool',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'cobbDouglasAlphaDenominator',
                outputs: [
                    {
                        name: '',
                        type: 'uint32',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'cobbDouglasAlphaNumerator',
                outputs: [
                    {
                        name: '',
                        type: 'uint32',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                    {
                        name: 'member',
                        type: 'address',
                    },
                ],
                name: 'computeRewardBalanceOfDelegator',
                outputs: [
                    {
                        name: 'reward',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                name: 'computeRewardBalanceOfOperator',
                outputs: [
                    {
                        name: 'reward',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'operatorShare',
                        type: 'uint32',
                    },
                    {
                        name: 'addOperatorAsMaker',
                        type: 'bool',
                    },
                ],
                name: 'createStakingPool',
                outputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'currentEpoch',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'currentEpochStartTimeInSeconds',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                    {
                        name: 'newOperatorShare',
                        type: 'uint32',
                    },
                ],
                name: 'decreaseStakingPoolOperatorShare',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: false,
                inputs: [],
                name: 'endEpoch',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'epochDurationInSeconds',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                name: 'finalizePool',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'getAuthorizedAddresses',
                outputs: [
                    {
                        name: '',
                        type: 'address[]',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'getCurrentEpochEarliestEndTimeInSeconds',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'stakeStatus',
                        type: 'uint8',
                    },
                ],
                name: 'getGlobalStakeByStatus',
                outputs: [
                    {
                        name: 'balance',
                        type: 'tuple',
                        components: [
                            {
                                name: 'currentEpoch',
                                type: 'uint64',
                            },
                            {
                                name: 'currentEpochBalance',
                                type: 'uint96',
                            },
                            {
                                name: 'nextEpochBalance',
                                type: 'uint96',
                            },
                        ],
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'staker',
                        type: 'address',
                    },
                    {
                        name: 'stakeStatus',
                        type: 'uint8',
                    },
                ],
                name: 'getOwnerStakeByStatus',
                outputs: [
                    {
                        name: 'balance',
                        type: 'tuple',
                        components: [
                            {
                                name: 'currentEpoch',
                                type: 'uint64',
                            },
                            {
                                name: 'currentEpochBalance',
                                type: 'uint96',
                            },
                            {
                                name: 'nextEpochBalance',
                                type: 'uint96',
                            },
                        ],
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'getParams',
                outputs: [
                    {
                        name: '_epochDurationInSeconds',
                        type: 'uint256',
                    },
                    {
                        name: '_rewardDelegatedStakeWeight',
                        type: 'uint32',
                    },
                    {
                        name: '_minimumPoolStake',
                        type: 'uint256',
                    },
                    {
                        name: '_cobbDouglasAlphaNumerator',
                        type: 'uint32',
                    },
                    {
                        name: '_cobbDouglasAlphaDenominator',
                        type: 'uint32',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'staker',
                        type: 'address',
                    },
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                name: 'getStakeDelegatedToPoolByOwner',
                outputs: [
                    {
                        name: 'balance',
                        type: 'tuple',
                        components: [
                            {
                                name: 'currentEpoch',
                                type: 'uint64',
                            },
                            {
                                name: 'currentEpochBalance',
                                type: 'uint96',
                            },
                            {
                                name: 'nextEpochBalance',
                                type: 'uint96',
                            },
                        ],
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                name: 'getStakingPool',
                outputs: [
                    {
                        name: '',
                        type: 'tuple',
                        components: [
                            {
                                name: 'operator',
                                type: 'address',
                            },
                            {
                                name: 'operatorShare',
                                type: 'uint32',
                            },
                        ],
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                name: 'getStakingPoolStatsThisEpoch',
                outputs: [
                    {
                        name: '',
                        type: 'tuple',
                        components: [
                            {
                                name: 'feesCollected',
                                type: 'uint256',
                            },
                            {
                                name: 'weightedStake',
                                type: 'uint256',
                            },
                            {
                                name: 'membersStake',
                                type: 'uint256',
                            },
                        ],
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'staker',
                        type: 'address',
                    },
                ],
                name: 'getTotalStake',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                name: 'getTotalStakeDelegatedToPool',
                outputs: [
                    {
                        name: 'balance',
                        type: 'tuple',
                        components: [
                            {
                                name: 'currentEpoch',
                                type: 'uint64',
                            },
                            {
                                name: 'currentEpochBalance',
                                type: 'uint96',
                            },
                            {
                                name: 'nextEpochBalance',
                                type: 'uint96',
                            },
                        ],
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'getWethContract',
                outputs: [
                    {
                        name: 'wethContract',
                        type: 'address',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'getZrxVault',
                outputs: [
                    {
                        name: 'zrxVault',
                        type: 'address',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [],
                name: 'init',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                name: 'joinStakingPoolAsMaker',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'lastPoolId',
                outputs: [
                    {
                        name: '',
                        type: 'bytes32',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'minimumPoolStake',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'from',
                        type: 'tuple',
                        components: [
                            {
                                name: 'status',
                                type: 'uint8',
                            },
                            {
                                name: 'poolId',
                                type: 'bytes32',
                            },
                        ],
                    },
                    {
                        name: 'to',
                        type: 'tuple',
                        components: [
                            {
                                name: 'status',
                                type: 'uint8',
                            },
                            {
                                name: 'poolId',
                                type: 'bytes32',
                            },
                        ],
                    },
                    {
                        name: 'amount',
                        type: 'uint256',
                    },
                ],
                name: 'moveStake',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'owner',
                outputs: [
                    {
                        name: '',
                        type: 'address',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'makerAddress',
                        type: 'address',
                    },
                    {
                        name: 'payerAddress',
                        type: 'address',
                    },
                    {
                        name: 'protocolFee',
                        type: 'uint256',
                    },
                ],
                name: 'payProtocolFee',
                outputs: [],
                payable: true,
                stateMutability: 'payable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'index_0',
                        type: 'address',
                    },
                ],
                name: 'poolIdByMaker',
                outputs: [
                    {
                        name: '',
                        type: 'bytes32',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'index_0',
                        type: 'bytes32',
                    },
                    {
                        name: 'index_1',
                        type: 'uint256',
                    },
                ],
                name: 'poolStatsByEpoch',
                outputs: [
                    {
                        name: 'feesCollected',
                        type: 'uint256',
                    },
                    {
                        name: 'weightedStake',
                        type: 'uint256',
                    },
                    {
                        name: 'membersStake',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'target',
                        type: 'address',
                    },
                ],
                name: 'removeAuthorizedAddress',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'target',
                        type: 'address',
                    },
                    {
                        name: 'index',
                        type: 'uint256',
                    },
                ],
                name: 'removeAuthorizedAddressAtIndex',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'addr',
                        type: 'address',
                    },
                ],
                name: 'removeExchangeAddress',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'rewardDelegatedStakeWeight',
                outputs: [
                    {
                        name: '',
                        type: 'uint32',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'index_0',
                        type: 'bytes32',
                    },
                ],
                name: 'rewardsByPoolId',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: '_epochDurationInSeconds',
                        type: 'uint256',
                    },
                    {
                        name: '_rewardDelegatedStakeWeight',
                        type: 'uint32',
                    },
                    {
                        name: '_minimumPoolStake',
                        type: 'uint256',
                    },
                    {
                        name: '_cobbDouglasAlphaNumerator',
                        type: 'uint32',
                    },
                    {
                        name: '_cobbDouglasAlphaDenominator',
                        type: 'uint32',
                    },
                ],
                name: 'setParams',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'amount',
                        type: 'uint256',
                    },
                ],
                name: 'stake',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'stakingContract',
                outputs: [
                    {
                        name: '',
                        type: 'address',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'newOwner',
                        type: 'address',
                    },
                ],
                name: 'transferOwnership',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'amount',
                        type: 'uint256',
                    },
                ],
                name: 'unstake',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
            {
                constant: true,
                inputs: [
                    {
                        name: 'index_0',
                        type: 'address',
                    },
                ],
                name: 'validExchanges',
                outputs: [
                    {
                        name: '',
                        type: 'bool',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: true,
                inputs: [],
                name: 'wethReservedForPoolRewards',
                outputs: [
                    {
                        name: '',
                        type: 'uint256',
                    },
                ],
                payable: false,
                stateMutability: 'view',
                type: 'function',
            },
            {
                constant: false,
                inputs: [
                    {
                        name: 'poolId',
                        type: 'bytes32',
                    },
                ],
                name: 'withdrawDelegatorRewards',
                outputs: [],
                payable: false,
                stateMutability: 'nonpayable',
                type: 'function',
            },
        ] as ContractAbi;
        return abi;
    }

    public getFunctionSignature(methodName: string): string {
        const index = this._methodABIIndex[methodName];
        const methodAbi = StakingContract.ABI()[index] as MethodAbi; // tslint:disable-line:no-unnecessary-type-assertion
        const functionSignature = methodAbiToFunctionSignature(methodAbi);
        return functionSignature;
    }
    public getABIDecodedTransactionData<T>(methodName: string, callData: string): T {
        const functionSignature = this.getFunctionSignature(methodName);
        const self = (this as any) as StakingContract;
        const abiEncoder = self._lookupAbiEncoder(functionSignature);
        const abiDecodedCallData = abiEncoder.strictDecode<T>(callData);
        return abiDecodedCallData;
    }
    public getABIDecodedReturnData<T>(methodName: string, callData: string): T {
        const functionSignature = this.getFunctionSignature(methodName);
        const self = (this as any) as StakingContract;
        const abiEncoder = self._lookupAbiEncoder(functionSignature);
        const abiDecodedCallData = abiEncoder.strictDecodeReturnValue<T>(callData);
        return abiDecodedCallData;
    }
    public getSelector(methodName: string): string {
        const functionSignature = this.getFunctionSignature(methodName);
        const self = (this as any) as StakingContract;
        const abiEncoder = self._lookupAbiEncoder(functionSignature);
        return abiEncoder.getSelector();
    }

    /**
     * Authorizes an address.
     * @param target Address to authorize.
     */
    public addAuthorizedAddress(target: string): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('target', target);
        const functionSignature = 'addAuthorizedAddress(address)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [target.toLowerCase()]);
            },
        };
    }
    /**
     * Adds a new exchange address
     * @param addr Address of exchange contract to add
     */
    public addExchangeAddress(addr: string): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('addr', addr);
        const functionSignature = 'addExchangeAddress(address)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [addr.toLowerCase()]);
            },
        };
    }
    public aggregatedStatsByEpoch(
        index_0: BigNumber,
    ): ContractFunctionObj<[BigNumber, BigNumber, BigNumber, BigNumber, BigNumber]> {
        const self = (this as any) as StakingContract;
        assert.isBigNumber('index_0', index_0);
        const functionSignature = 'aggregatedStatsByEpoch(uint256)';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<[BigNumber, BigNumber, BigNumber, BigNumber, BigNumber]> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<[BigNumber, BigNumber, BigNumber, BigNumber, BigNumber]>(
                    rawCallResult,
                );
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [index_0]);
            },
        };
    }
    public authorities(index_0: BigNumber): ContractFunctionObj<string> {
        const self = (this as any) as StakingContract;
        assert.isBigNumber('index_0', index_0);
        const functionSignature = 'authorities(uint256)';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [index_0]);
            },
        };
    }
    public authorized(index_0: string): ContractFunctionObj<boolean> {
        const self = (this as any) as StakingContract;
        assert.isString('index_0', index_0);
        const functionSignature = 'authorized(address)';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<boolean> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<boolean>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [index_0.toLowerCase()]);
            },
        };
    }
    public cobbDouglasAlphaDenominator(): ContractFunctionObj<number> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'cobbDouglasAlphaDenominator()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<number> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<number>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    public cobbDouglasAlphaNumerator(): ContractFunctionObj<number> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'cobbDouglasAlphaNumerator()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<number> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<number>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Computes the reward balance in ETH of a specific member of a pool.
     * @param poolId Unique id of pool.
     * @param member The member of the pool.
     * @returns totalReward Balance in ETH.
     */
    public computeRewardBalanceOfDelegator(poolId: string, member: string): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        assert.isString('member', member);
        const functionSignature = 'computeRewardBalanceOfDelegator(bytes32,address)';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId, member.toLowerCase()]);
            },
        };
    }
    /**
     * Computes the reward balance in ETH of the operator of a pool.
     * @param poolId Unique id of pool.
     * @returns totalReward Balance in ETH.
     */
    public computeRewardBalanceOfOperator(poolId: string): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        const functionSignature = 'computeRewardBalanceOfOperator(bytes32)';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId]);
            },
        };
    }
    /**
     * Create a new staking pool. The sender will be the operator of this pool. Note that an operator must be payable.
     * @param operatorShare Portion of rewards owned by the operator, in ppm.
     * @param addOperatorAsMaker Adds operator to the created pool as a maker for
     *     convenience iff true.
     * @returns poolId The unique pool id generated for this pool.
     */
    public createStakingPool(
        operatorShare: number | BigNumber,
        addOperatorAsMaker: boolean,
    ): ContractTxFunctionObj<string> {
        const self = (this as any) as StakingContract;
        assert.isNumberOrBigNumber('operatorShare', operatorShare);
        assert.isBoolean('addOperatorAsMaker', addOperatorAsMaker);
        const functionSignature = 'createStakingPool(uint32,bool)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [operatorShare, addOperatorAsMaker]);
            },
        };
    }
    public currentEpoch(): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'currentEpoch()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    public currentEpochStartTimeInSeconds(): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'currentEpochStartTimeInSeconds()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Decreases the operator share for the given pool (i.e. increases pool rewards for members).
     * @param poolId Unique Id of pool.
     * @param newOperatorShare The newly decreased percentage of any rewards owned
     *     by the operator.
     */
    public decreaseStakingPoolOperatorShare(
        poolId: string,
        newOperatorShare: number | BigNumber,
    ): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        assert.isNumberOrBigNumber('newOperatorShare', newOperatorShare);
        const functionSignature = 'decreaseStakingPoolOperatorShare(bytes32,uint32)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId, newOperatorShare]);
            },
        };
    }
    /**
     * Begins a new epoch, preparing the prior one for finalization.
     * Throws if not enough time has passed between epochs or if the
     * previous epoch was not fully finalized.
     * @returns numPoolsToFinalize The number of unfinalized pools.
     */
    public endEpoch(): ContractTxFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'endEpoch()';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    public epochDurationInSeconds(): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'epochDurationInSeconds()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Instantly finalizes a single pool that earned rewards in the previous
     * epoch, crediting it rewards for members and withdrawing operator's
     * rewards as WETH. This can be called by internal functions that need
     * to finalize a pool immediately. Does nothing if the pool is already
     * finalized or did not earn rewards in the previous epoch.
     * @param poolId The pool ID to finalize.
     */
    public finalizePool(poolId: string): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        const functionSignature = 'finalizePool(bytes32)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId]);
            },
        };
    }
    /**
     * Gets all authorized addresses.
     * @returns Array of authorized addresses.
     */
    public getAuthorizedAddresses(): ContractFunctionObj<string[]> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'getAuthorizedAddresses()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string[]> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string[]>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Returns the earliest end time in seconds of this epoch.
     * The next epoch can begin once this time is reached.
     * Epoch period = [startTimeInSeconds..endTimeInSeconds)
     * @returns Time in seconds.
     */
    public getCurrentEpochEarliestEndTimeInSeconds(): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'getCurrentEpochEarliestEndTimeInSeconds()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Gets global stake for a given status.
     * @param stakeStatus UNDELEGATED or DELEGATED
     * @returns Global stake for given status.
     */
    public getGlobalStakeByStatus(
        stakeStatus: number | BigNumber,
    ): ContractFunctionObj<{ currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber }> {
        const self = (this as any) as StakingContract;
        assert.isNumberOrBigNumber('stakeStatus', stakeStatus);
        const functionSignature = 'getGlobalStakeByStatus(uint8)';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<{ currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber }> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<{
                    currentEpoch: BigNumber;
                    currentEpochBalance: BigNumber;
                    nextEpochBalance: BigNumber;
                }>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [stakeStatus]);
            },
        };
    }
    /**
     * Gets an owner's stake balances by status.
     * @param staker Owner of stake.
     * @param stakeStatus UNDELEGATED or DELEGATED
     * @returns Owner&#x27;s stake balances for given status.
     */
    public getOwnerStakeByStatus(
        staker: string,
        stakeStatus: number | BigNumber,
    ): ContractFunctionObj<{ currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber }> {
        const self = (this as any) as StakingContract;
        assert.isString('staker', staker);
        assert.isNumberOrBigNumber('stakeStatus', stakeStatus);
        const functionSignature = 'getOwnerStakeByStatus(address,uint8)';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<{ currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber }> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<{
                    currentEpoch: BigNumber;
                    currentEpochBalance: BigNumber;
                    nextEpochBalance: BigNumber;
                }>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [staker.toLowerCase(), stakeStatus]);
            },
        };
    }
    /**
     * Retrieves all configurable parameter values.
     * @returns _epochDurationInSeconds Minimum seconds between epochs._rewardDelegatedStakeWeight How much delegated stake is weighted vs operator stake, in ppm._minimumPoolStake Minimum amount of stake required in a pool to collect rewards._cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor._cobbDouglasAlphaDenominator Denominator for cobb douglas alpha factor.
     */
    public getParams(): ContractFunctionObj<[BigNumber, number, BigNumber, number, number]> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'getParams()';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<[BigNumber, number, BigNumber, number, number]> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<[BigNumber, number, BigNumber, number, number]>(
                    rawCallResult,
                );
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Returns the stake delegated to a specific staking pool, by a given staker.
     * @param staker of stake.
     * @param poolId Unique Id of pool.
     * @returns Stake delegated to pool by staker.
     */
    public getStakeDelegatedToPoolByOwner(
        staker: string,
        poolId: string,
    ): ContractFunctionObj<{ currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber }> {
        const self = (this as any) as StakingContract;
        assert.isString('staker', staker);
        assert.isString('poolId', poolId);
        const functionSignature = 'getStakeDelegatedToPoolByOwner(address,bytes32)';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<{ currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber }> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<{
                    currentEpoch: BigNumber;
                    currentEpochBalance: BigNumber;
                    nextEpochBalance: BigNumber;
                }>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [staker.toLowerCase(), poolId]);
            },
        };
    }
    /**
     * Returns a staking pool
     * @param poolId Unique id of pool.
     */
    public getStakingPool(poolId: string): ContractFunctionObj<{ operator: string; operatorShare: number }> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        const functionSignature = 'getStakingPool(bytes32)';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<{ operator: string; operatorShare: number }> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<{ operator: string; operatorShare: number }>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId]);
            },
        };
    }
    /**
     * Get stats on a staking pool in this epoch.
     * @param poolId Pool Id to query.
     * @returns PoolStats struct for pool id.
     */
    public getStakingPoolStatsThisEpoch(
        poolId: string,
    ): ContractFunctionObj<{ feesCollected: BigNumber; weightedStake: BigNumber; membersStake: BigNumber }> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        const functionSignature = 'getStakingPoolStatsThisEpoch(bytes32)';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<{ feesCollected: BigNumber; weightedStake: BigNumber; membersStake: BigNumber }> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<{
                    feesCollected: BigNumber;
                    weightedStake: BigNumber;
                    membersStake: BigNumber;
                }>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId]);
            },
        };
    }
    /**
     * Returns the total stake for a given staker.
     * @param staker of stake.
     * @returns Total ZRX staked by &#x60;staker&#x60;.
     */
    public getTotalStake(staker: string): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        assert.isString('staker', staker);
        const functionSignature = 'getTotalStake(address)';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [staker.toLowerCase()]);
            },
        };
    }
    /**
     * Returns the total stake delegated to a specific staking pool,
     * across all members.
     * @param poolId Unique Id of pool.
     * @returns Total stake delegated to pool.
     */
    public getTotalStakeDelegatedToPool(
        poolId: string,
    ): ContractFunctionObj<{ currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber }> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        const functionSignature = 'getTotalStakeDelegatedToPool(bytes32)';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<{ currentEpoch: BigNumber; currentEpochBalance: BigNumber; nextEpochBalance: BigNumber }> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<{
                    currentEpoch: BigNumber;
                    currentEpochBalance: BigNumber;
                    nextEpochBalance: BigNumber;
                }>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId]);
            },
        };
    }
    /**
     * Returns the current weth contract address
     * @returns wethContract The WETH contract instance.
     */
    public getWethContract(): ContractFunctionObj<string> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'getWethContract()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Returns the current zrxVault address.
     * @returns zrxVault The zrxVault contract.
     */
    public getZrxVault(): ContractFunctionObj<string> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'getZrxVault()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Initialize storage owned by this contract.
     * This function should not be called directly.
     * The StakingProxy contract will call it in `attachStakingContract()`.
     */
    public init(): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'init()';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Allows caller to join a staking pool as a maker.
     * @param poolId Unique id of pool.
     */
    public joinStakingPoolAsMaker(poolId: string): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        const functionSignature = 'joinStakingPoolAsMaker(bytes32)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId]);
            },
        };
    }
    public lastPoolId(): ContractFunctionObj<string> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'lastPoolId()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    public minimumPoolStake(): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'minimumPoolStake()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Moves stake between statuses: 'undelegated' or 'delegated'.
     * Delegated stake can also be moved between pools.
     * This change comes into effect next epoch.
     * @param from status to move stake out of.
     * @param to status to move stake into.
     * @param amount of stake to move.
     */
    public moveStake(
        from: { status: number | BigNumber; poolId: string },
        to: { status: number | BigNumber; poolId: string },
        amount: BigNumber,
    ): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;

        assert.isBigNumber('amount', amount);
        const functionSignature = 'moveStake((uint8,bytes32),(uint8,bytes32),uint256)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [from, to, amount]);
            },
        };
    }
    public owner(): ContractFunctionObj<string> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'owner()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Pays a protocol fee in ETH or WETH.
     * Only a known 0x exchange can call this method. See
     * (MixinExchangeManager).
     * @param makerAddress The address of the order's maker.
     * @param payerAddress The address of the protocol fee payer.
     * @param protocolFee The protocol fee amount. This is either passed as ETH or
     *     transferred as WETH.
     */
    public payProtocolFee(
        makerAddress: string,
        payerAddress: string,
        protocolFee: BigNumber,
    ): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('makerAddress', makerAddress);
        assert.isString('payerAddress', payerAddress);
        assert.isBigNumber('protocolFee', protocolFee);
        const functionSignature = 'payProtocolFee(address,address,uint256)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [
                    makerAddress.toLowerCase(),
                    payerAddress.toLowerCase(),
                    protocolFee,
                ]);
            },
        };
    }
    public poolIdByMaker(index_0: string): ContractFunctionObj<string> {
        const self = (this as any) as StakingContract;
        assert.isString('index_0', index_0);
        const functionSignature = 'poolIdByMaker(address)';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [index_0.toLowerCase()]);
            },
        };
    }
    public poolStatsByEpoch(
        index_0: string,
        index_1: BigNumber,
    ): ContractFunctionObj<[BigNumber, BigNumber, BigNumber]> {
        const self = (this as any) as StakingContract;
        assert.isString('index_0', index_0);
        assert.isBigNumber('index_1', index_1);
        const functionSignature = 'poolStatsByEpoch(bytes32,uint256)';

        return {
            async callAsync(
                callData: Partial<CallData> = {},
                defaultBlock?: BlockParam,
            ): Promise<[BigNumber, BigNumber, BigNumber]> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<[BigNumber, BigNumber, BigNumber]>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [index_0, index_1]);
            },
        };
    }
    /**
     * Removes authorizion of an address.
     * @param target Address to remove authorization from.
     */
    public removeAuthorizedAddress(target: string): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('target', target);
        const functionSignature = 'removeAuthorizedAddress(address)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [target.toLowerCase()]);
            },
        };
    }
    /**
     * Removes authorizion of an address.
     * @param target Address to remove authorization from.
     * @param index Index of target in authorities array.
     */
    public removeAuthorizedAddressAtIndex(target: string, index: BigNumber): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('target', target);
        assert.isBigNumber('index', index);
        const functionSignature = 'removeAuthorizedAddressAtIndex(address,uint256)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [target.toLowerCase(), index]);
            },
        };
    }
    /**
     * Removes an existing exchange address
     * @param addr Address of exchange contract to remove
     */
    public removeExchangeAddress(addr: string): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('addr', addr);
        const functionSignature = 'removeExchangeAddress(address)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [addr.toLowerCase()]);
            },
        };
    }
    public rewardDelegatedStakeWeight(): ContractFunctionObj<number> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'rewardDelegatedStakeWeight()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<number> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<number>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    public rewardsByPoolId(index_0: string): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        assert.isString('index_0', index_0);
        const functionSignature = 'rewardsByPoolId(bytes32)';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [index_0]);
            },
        };
    }
    /**
     * Set all configurable parameters at once.
     * @param _epochDurationInSeconds Minimum seconds between epochs.
     * @param _rewardDelegatedStakeWeight How much delegated stake is weighted vs
     *     operator stake, in ppm.
     * @param _minimumPoolStake Minimum amount of stake required in a pool to
     *     collect rewards.
     * @param _cobbDouglasAlphaNumerator Numerator for cobb douglas alpha factor.
     * @param _cobbDouglasAlphaDenominator Denominator for cobb douglas alpha
     *     factor.
     */
    public setParams(
        _epochDurationInSeconds: BigNumber,
        _rewardDelegatedStakeWeight: number | BigNumber,
        _minimumPoolStake: BigNumber,
        _cobbDouglasAlphaNumerator: number | BigNumber,
        _cobbDouglasAlphaDenominator: number | BigNumber,
    ): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isBigNumber('_epochDurationInSeconds', _epochDurationInSeconds);
        assert.isNumberOrBigNumber('_rewardDelegatedStakeWeight', _rewardDelegatedStakeWeight);
        assert.isBigNumber('_minimumPoolStake', _minimumPoolStake);
        assert.isNumberOrBigNumber('_cobbDouglasAlphaNumerator', _cobbDouglasAlphaNumerator);
        assert.isNumberOrBigNumber('_cobbDouglasAlphaDenominator', _cobbDouglasAlphaDenominator);
        const functionSignature = 'setParams(uint256,uint32,uint256,uint32,uint32)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [
                    _epochDurationInSeconds,
                    _rewardDelegatedStakeWeight,
                    _minimumPoolStake,
                    _cobbDouglasAlphaNumerator,
                    _cobbDouglasAlphaDenominator,
                ]);
            },
        };
    }
    /**
     * Stake ZRX tokens. Tokens are deposited into the ZRX Vault.
     * Unstake to retrieve the ZRX. Stake is in the 'Active' status.
     * @param amount of ZRX to stake.
     */
    public stake(amount: BigNumber): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isBigNumber('amount', amount);
        const functionSignature = 'stake(uint256)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [amount]);
            },
        };
    }
    public stakingContract(): ContractFunctionObj<string> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'stakingContract()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<string> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<string>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    public transferOwnership(newOwner: string): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('newOwner', newOwner);
        const functionSignature = 'transferOwnership(address)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [newOwner.toLowerCase()]);
            },
        };
    }
    /**
     * Unstake. Tokens are withdrawn from the ZRX Vault and returned to
     * the staker. Stake must be in the 'undelegated' status in both the
     * current and next epoch in order to be unstaked.
     * @param amount of ZRX to unstake.
     */
    public unstake(amount: BigNumber): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isBigNumber('amount', amount);
        const functionSignature = 'unstake(uint256)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [amount]);
            },
        };
    }
    public validExchanges(index_0: string): ContractFunctionObj<boolean> {
        const self = (this as any) as StakingContract;
        assert.isString('index_0', index_0);
        const functionSignature = 'validExchanges(address)';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<boolean> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<boolean>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [index_0.toLowerCase()]);
            },
        };
    }
    public wethReservedForPoolRewards(): ContractFunctionObj<BigNumber> {
        const self = (this as any) as StakingContract;
        const functionSignature = 'wethReservedForPoolRewards()';

        return {
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<BigNumber> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<BigNumber>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, []);
            },
        };
    }
    /**
     * Withdraws the caller's WETH rewards that have accumulated
     * until the last epoch.
     * @param poolId Unique id of pool.
     */
    public withdrawDelegatorRewards(poolId: string): ContractTxFunctionObj<void> {
        const self = (this as any) as StakingContract;
        assert.isString('poolId', poolId);
        const functionSignature = 'withdrawDelegatorRewards(bytes32)';

        return {
            async sendTransactionAsync(
                txData?: Partial<TxData> | undefined,
                opts: SendTransactionOpts = { shouldValidate: true },
            ): Promise<string> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync(
                    { ...txData, data: this.getABIEncodedTransactionData() },
                    this.estimateGasAsync.bind(this),
                );
                if (opts.shouldValidate !== false) {
                    await this.callAsync(txDataWithDefaults);
                }
                return self._web3Wrapper.sendTransactionAsync(txDataWithDefaults);
            },
            awaitTransactionSuccessAsync(
                txData?: Partial<TxData>,
                opts: AwaitTransactionSuccessOpts = { shouldValidate: true },
            ): PromiseWithTransactionHash<TransactionReceiptWithDecodedLogs> {
                return self._promiseWithTransactionHash(this.sendTransactionAsync(txData, opts), opts);
            },
            async estimateGasAsync(txData?: Partial<TxData> | undefined): Promise<number> {
                const txDataWithDefaults = await self._applyDefaultsToTxDataAsync({
                    ...txData,
                    data: this.getABIEncodedTransactionData(),
                });
                return self._web3Wrapper.estimateGasAsync(txDataWithDefaults);
            },
            async callAsync(callData: Partial<CallData> = {}, defaultBlock?: BlockParam): Promise<void> {
                BaseContract._assertCallParams(callData, defaultBlock);
                const rawCallResult = await self._performCallAsync(
                    { ...callData, data: this.getABIEncodedTransactionData() },
                    defaultBlock,
                );
                const abiEncoder = self._lookupAbiEncoder(functionSignature);
                return abiEncoder.strictDecodeReturnValue<void>(rawCallResult);
            },
            getABIEncodedTransactionData(): string {
                return self._strictEncodeArguments(functionSignature, [poolId]);
            },
        };
    }

    /**
     * Subscribe to an event type emitted by the Staking contract.
     * @param eventName The Staking contract event you would like to subscribe to.
     * @param indexFilterValues An object where the keys are indexed args returned by the event and
     * the value is the value you are interested in. E.g `{maker: aUserAddressHex}`
     * @param callback Callback that gets called when a log is added/removed
     * @param isVerbose Enable verbose subscription warnings (e.g recoverable network issues encountered)
     * @return Subscription token used later to unsubscribe
     */
    public subscribe<ArgsType extends StakingEventArgs>(
        eventName: StakingEvents,
        indexFilterValues: IndexedFilterValues,
        callback: EventCallback<ArgsType>,
        isVerbose: boolean = false,
        blockPollingIntervalMs?: number,
    ): string {
        assert.doesBelongToStringEnum('eventName', eventName, StakingEvents);
        assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
        assert.isFunction('callback', callback);
        const subscriptionToken = this._subscriptionManager.subscribe<ArgsType>(
            this.address,
            eventName,
            indexFilterValues,
            StakingContract.ABI(),
            callback,
            isVerbose,
            blockPollingIntervalMs,
        );
        return subscriptionToken;
    }
    /**
     * Cancel a subscription
     * @param subscriptionToken Subscription token returned by `subscribe()`
     */
    public unsubscribe(subscriptionToken: string): void {
        this._subscriptionManager.unsubscribe(subscriptionToken);
    }
    /**
     * Cancels all existing subscriptions
     */
    public unsubscribeAll(): void {
        this._subscriptionManager.unsubscribeAll();
    }
    /**
     * Gets historical logs without creating a subscription
     * @param eventName The Staking contract event you would like to subscribe to.
     * @param blockRange Block range to get logs from.
     * @param indexFilterValues An object where the keys are indexed args returned by the event and
     * the value is the value you are interested in. E.g `{_from: aUserAddressHex}`
     * @return Array of logs that match the parameters
     */
    public async getLogsAsync<ArgsType extends StakingEventArgs>(
        eventName: StakingEvents,
        blockRange: BlockRange,
        indexFilterValues: IndexedFilterValues,
    ): Promise<Array<LogWithDecodedArgs<ArgsType>>> {
        assert.doesBelongToStringEnum('eventName', eventName, StakingEvents);
        assert.doesConformToSchema('blockRange', blockRange, schemas.blockRangeSchema);
        assert.doesConformToSchema('indexFilterValues', indexFilterValues, schemas.indexFilterValuesSchema);
        const logs = await this._subscriptionManager.getLogsAsync<ArgsType>(
            this.address,
            eventName,
            blockRange,
            indexFilterValues,
            StakingContract.ABI(),
        );
        return logs;
    }
    constructor(
        address: string,
        supportedProvider: SupportedProvider,
        txDefaults?: Partial<TxData>,
        logDecodeDependencies?: { [contractName: string]: ContractAbi },
        deployedBytecode: string | undefined = StakingContract.deployedBytecode,
    ) {
        super(
            'Staking',
            StakingContract.ABI(),
            address,
            supportedProvider,
            txDefaults,
            logDecodeDependencies,
            deployedBytecode,
        );
        classUtils.bindAll(this, ['_abiEncoderByFunctionSignature', 'address', '_web3Wrapper']);
        this._subscriptionManager = new SubscriptionManager<StakingEventArgs, StakingEvents>(
            StakingContract.ABI(),
            this._web3Wrapper,
        );
        StakingContract.ABI().forEach((item, index) => {
            if (item.type === 'function') {
                const methodAbi = item as MethodAbi;
                this._methodABIIndex[methodAbi.name] = index;
            }
        });
    }
}

// tslint:disable:max-file-line-count
// tslint:enable:no-unbound-method no-parameter-reassignment no-consecutive-blank-lines ordered-imports align
// tslint:enable:trailing-comma whitespace no-trailing-whitespace
