UNPKG

@dydxfoundation/governance

Version:
254 lines (253 loc) 11.1 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const utils_1 = require("ethers/lib/utils"); const types_1 = require("../../../types"); const config_1 = require("../config"); const types_2 = require("../types"); const parsings_1 = require("../utils/parsings"); const methodValidators_1 = require("../validators/methodValidators"); const paramValidators_1 = require("../validators/paramValidators"); const BaseService_1 = __importDefault(require("./BaseService")); class LiquidityModule extends BaseService_1.default { constructor(config, erc20Service, hardhatLiquidityModuleAddresses) { super(config, types_1.LiquidityStakingV1__factory); this.erc20Service = erc20Service; this._stakedToken = null; this._rewardToken = null; // Get the staking contract address. const { network } = this.config; const isHardhatNetwork = network === types_2.Network.hardhat; if (isHardhatNetwork && !hardhatLiquidityModuleAddresses) { throw new Error('Must specify staking addresses when on hardhat network'); } const networkStakingAddresses = isHardhatNetwork ? hardhatLiquidityModuleAddresses : config_1.liquidityModuleAddresses[network]; this.liquidityModuleAddress = networkStakingAddresses.LIQUIDITY_MODULE_ADDRESS; } get contract() { return this.getContractInstance(this.liquidityModuleAddress); } async getStakedToken() { if (!this._stakedToken) { this._stakedToken = await this.contract.STAKED_TOKEN(); } return this._stakedToken; } async getRewardToken() { if (!this._rewardToken) { this._rewardToken = await this.contract.REWARDS_TOKEN(); } return this._rewardToken; } async stake(user, amount, onBehalfOf, gasLimit) { const txs = []; const { approve } = this.erc20Service; const stakedToken = await this.getStakedToken(); const stakedTokenDecimals = config_1.USDC_TOKEN_DECIMALS; const convertedAmount = (0, parsings_1.parseNumberToString)(amount, stakedTokenDecimals); const allowance = (0, parsings_1.parseNumberToEthersBigNumber)(await this.allowance(user), stakedTokenDecimals); if (allowance.lt(convertedAmount)) { // user has an approval value for spender of less than `convertedAmount` const approveTx = approve(stakedToken, user, this.liquidityModuleAddress, config_1.DEFAULT_APPROVE_AMOUNT); txs.push(approveTx); } let txCallback; if (onBehalfOf) { txCallback = this.generateTxCallback({ rawTxMethod: () => this.contract.populateTransaction.stakeFor(onBehalfOf, convertedAmount), from: user, gasLimit, }); } else { txCallback = this.generateTxCallback({ rawTxMethod: () => this.contract.populateTransaction.stake(convertedAmount), from: user, gasLimit, }); } txs.push({ tx: txCallback, txType: types_2.eEthereumTxType.LIQUIDITY_MODULE_ACTION, gas: this.generateTxPriceEstimation(txs, txCallback), }); return txs; } async withdrawStake(user, amount, recipient) { let convertedAmount; if (amount === '-1') { convertedAmount = config_1.MAX_UINT_AMOUNT; } else { convertedAmount = (0, parsings_1.parseNumberToString)(amount, config_1.USDC_TOKEN_DECIMALS); } let txCallback; if (convertedAmount === config_1.MAX_UINT_AMOUNT) { txCallback = this.generateTxCallback({ rawTxMethod: () => this.contract.populateTransaction.withdrawMaxStake(recipient || user), from: user, gasSurplus: 20, }); } else { txCallback = this.generateTxCallback({ rawTxMethod: () => this.contract.populateTransaction.withdrawStake(recipient || user, convertedAmount), from: user, gasSurplus: 20, }); } return [ { tx: txCallback, txType: types_2.eEthereumTxType.LIQUIDITY_MODULE_ACTION, gas: this.generateTxPriceEstimation([], txCallback), }, ]; } async withdrawDebt(user, amount, recipient) { let convertedAmount; if (amount === '-1') { convertedAmount = config_1.MAX_UINT_AMOUNT; } else { convertedAmount = (0, parsings_1.parseNumberToString)(amount, config_1.USDC_TOKEN_DECIMALS); } let txCallback; if (convertedAmount === config_1.MAX_UINT_AMOUNT) { txCallback = this.generateTxCallback({ rawTxMethod: () => this.contract.populateTransaction.withdrawMaxDebt(recipient || user), from: user, gasSurplus: 20, }); } else { txCallback = this.generateTxCallback({ rawTxMethod: () => this.contract.populateTransaction.withdrawDebt(recipient || user, convertedAmount), from: user, gasSurplus: 20, }); } return [ { tx: txCallback, txType: types_2.eEthereumTxType.LIQUIDITY_MODULE_ACTION, gas: this.generateTxPriceEstimation([], txCallback), }, ]; } async requestWithdrawal(user, amount) { const convertedAmount = (0, parsings_1.parseNumberToString)(amount, config_1.USDC_TOKEN_DECIMALS); const txCallback = this.generateTxCallback({ rawTxMethod: () => this.contract.populateTransaction.requestWithdrawal(convertedAmount), from: user, gasSurplus: 20, }); return [ { tx: txCallback, txType: types_2.eEthereumTxType.LIQUIDITY_MODULE_ACTION, gas: this.generateTxPriceEstimation([], txCallback), }, ]; } async claimRewards(user, recipient) { const txCallback = this.generateTxCallback({ rawTxMethod: () => this.contract.populateTransaction.claimRewards(recipient || user), from: user, gasSurplus: 20, }); return [ { tx: txCallback, txType: types_2.eEthereumTxType.LIQUIDITY_MODULE_ACTION, gas: this.generateTxPriceEstimation([], txCallback), }, ]; } async getTotalStake() { const currentActiveBalance = await this.contract.getTotalActiveBalanceCurrentEpoch(); return (0, utils_1.formatUnits)(currentActiveBalance, config_1.USDC_TOKEN_DECIMALS); } async getRewardsPerSecond() { const rewardsPerSecond = await this.contract.getRewardsPerSecond(); return (0, utils_1.formatUnits)(rewardsPerSecond, config_1.DYDX_TOKEN_DECIMALS); } async allowance(user) { return this.erc20Service.allowance(await this.getStakedToken(), user, this.liquidityModuleAddress); } async getUserStake(user) { return this.erc20Service.balanceOf(this.liquidityModuleAddress, user); } async getUserBalanceOfStakedToken(user) { const stakedTokenAddress = await this.getStakedToken(); return this.erc20Service.balanceOf(stakedTokenAddress, user); } async getUserStakeAvailableToWithdraw(user) { const userStakeAvailableToWithdraw = await this.contract.getStakeAvailableToWithdraw(user); return (0, utils_1.formatUnits)(userStakeAvailableToWithdraw, config_1.USDC_TOKEN_DECIMALS); } async getUserStakePendingWithdraw(user) { const [currentEpochInactive, nextEpochInactive,] = await Promise.all([ this.contract.getInactiveBalanceCurrentEpoch(user), this.contract.getInactiveBalanceNextEpoch(user), ]); const userStakePendingWithdrawal = nextEpochInactive.sub(currentEpochInactive); return (0, utils_1.formatUnits)(userStakePendingWithdrawal, config_1.USDC_TOKEN_DECIMALS); } async getUserUnclaimedRewards(user) { const userUnclaimedRewards = await this.contract.callStatic.claimRewards(user, { from: user }); return (0, utils_1.formatUnits)(userUnclaimedRewards, config_1.DYDX_TOKEN_DECIMALS); } async getTimeRemainingInCurrentEpoch() { return this.contract.getTimeRemainingInCurrentEpoch(); } async getLengthOfBlackoutWindow() { return this.contract.getBlackoutWindow(); } } __decorate([ methodValidators_1.StakingValidator, __param(0, (0, paramValidators_1.IsEthAddress)()), __param(1, (0, paramValidators_1.IsPositiveAmount)()), __param(2, paramValidators_1.Optional), __param(2, (0, paramValidators_1.IsEthAddress)()) ], LiquidityModule.prototype, "stake", null); __decorate([ methodValidators_1.StakingValidator, __param(0, (0, paramValidators_1.IsEthAddress)()), __param(1, (0, paramValidators_1.IsPositiveOrMinusOneAmount)()), __param(2, paramValidators_1.Optional), __param(2, (0, paramValidators_1.IsEthAddress)()) ], LiquidityModule.prototype, "withdrawStake", null); __decorate([ methodValidators_1.StakingValidator, __param(0, (0, paramValidators_1.IsEthAddress)()), __param(1, (0, paramValidators_1.IsPositiveOrMinusOneAmount)()), __param(2, paramValidators_1.Optional), __param(2, (0, paramValidators_1.IsEthAddress)()) ], LiquidityModule.prototype, "withdrawDebt", null); __decorate([ methodValidators_1.StakingValidator, __param(0, (0, paramValidators_1.IsEthAddress)()), __param(1, (0, paramValidators_1.IsPositiveAmount)()) ], LiquidityModule.prototype, "requestWithdrawal", null); __decorate([ methodValidators_1.StakingValidator, __param(0, (0, paramValidators_1.IsEthAddress)()), __param(1, paramValidators_1.Optional), __param(1, (0, paramValidators_1.IsEthAddress)()) ], LiquidityModule.prototype, "claimRewards", null); exports.default = LiquidityModule;