interface IUniStaker is IRageQuit {
    /* admin events */

    event UniStakerCreated(address rewardPool, address powerSwitch);
    event UniStakerFunded(address token, uint256 amount);
    event BonusTokenRegistered(address token);
    event BonusTokenRemoved(address token);
    event VaultFactoryRegistered(address factory);
    event VaultFactoryRemoved(address factory);
    event AdminshipTransferred(address indexed previousAdmin, address indexed newAdmin);

    /* user events */

    event Staked(address vault, uint256 amount);
    event Unstaked(address vault, uint256 amount);
    event RageQuit(address vault);
    event RewardClaimed(address vaultFactory, address recipient, address token, uint256 amount);
    event VestedRewardClaimed(address recipient, address token, uint amount);

    /* data types */

    struct VaultData {
        // token address to total token stake mapping
        mapping(address => uint) tokenStake;
        EnumerableSet.AddressSet tokens;
    }

    struct LMRewardData {
        uint256 amount;
        uint256 duration;
        uint256 startedAt;
        address rewardCalcInstance;
        EnumerableSet.AddressSet bonusTokens;
        mapping(address => uint) bonusTokenAmounts;
    }

    struct LMRewardVestingData {
        uint amount;
        uint startedAt;
    }

    /* getter functions */
    function getBonusTokenSetLength() external view returns (uint256 length);

    function getBonusTokenAtIndex(uint256 index) external view returns (address bonusToken);

    function getVaultFactorySetLength() external view returns (uint256 length);

    function getVaultFactoryAtIndex(uint256 index) external view returns (address factory);

    function getNumVaults() external view returns (uint256 num);

    function getVaultAt(uint256 index) external view returns (address vault);

    function getNumTokensStaked() external view returns (uint256 num);

    function getTokenStakedAt(uint256 index) external view returns (address token);

    function getNumTokensStakedInVault(address vault) external view returns (uint256 num);

    function getVaultTokenAtIndex(address vault, uint256 index) external view returns (address vaultToken);

    function getVaultTokenStake(address vault, address token) external view returns (uint256 tokenStake);

    function getLMRewardData(address token) external view returns (uint amount, uint duration, uint startedAt, address rewardCalcInstance);

    function getLMRewardBonusTokensLength(address token) external view returns (uint length);

    function getLMRewardBonusTokenAt(address token, uint index) external view returns (address bonusToken, uint bonusTokenAmount);

    function getNumVestingLMTokenRewards(address user) external view returns (uint num);

    function getVestingLMTokenAt(address user, uint index) external view returns (address token);

    function getNumVests(address user, address token) external view returns (uint num);

    function getNumRewardCalcTemplates() external view returns (uint num);

    function getLMRewardVestingData(address user, address token, uint index) external view returns (uint amount, uint startedAt);

    function isValidAddress(address target) external view returns (bool validity);

    function isValidVault(address vault, address factory) external view returns (bool validity);

    /* user functions */

    function stake(
        address vault,
        address vaultFactory,
        address token,
        uint256 amount,
        bytes calldata permission
    ) external;

    function unstakeAndClaim(
        address vault,
        address vaultFactory,
        address recipient,
        address token,
        uint256 amount,
        bool claimBonusReward,
        bytes calldata permission
    ) external;

    function claimAirdropReward(address nftFactory) external;

    function claimAirdropReward(address nftFactory, uint256[] calldata tokenIds) external;

    function claimVestedReward() external;

    function claimVestedReward(address token) external;
}
function stake(
    address vault,
    address vaultFactory,
    address token,
    uint256 amount,
    bytes calldata permission
) external;

/* user functions */