UNPKG

@superfluid-finance/sdk-core

Version:
232 lines 11.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.clipDepositNumber = exports.getFlowOperatorId = exports.typeGuard = exports.isInjectedEthers = exports.isInjectedWeb3 = exports.isEthersProvider = exports.calculateAvailableBalance = exports.getSanitizedTimestamp = exports.getStringCurrentTimeInSeconds = exports.subscriptionTotalAmountClaimableSinceUpdatedAt = exports.subscriptionTotalAmountReceivedSinceUpdated = exports.subscriptionTotalAmountDistributedSinceUpdated = exports.flowedAmountSinceUpdatedAt = exports.getFlowAmountByPerSecondFlowRate = exports.getPerSecondFlowRateByDay = exports.getPerSecondFlowRateByWeek = exports.getPerSecondFlowRateByMonth = exports.getPerSecondFlowRateByYear = exports.getTransactionDescription = exports.removeSigHashFromCallData = exports.isNullOrEmpty = exports._removePermissions = exports._addPermissions = exports.isPermissionsClean = exports.normalizeAddress = void 0; exports.toBN = toBN; exports.tryGet = tryGet; const ethers_1 = require("ethers"); const SFError_1 = require("./SFError"); const constants_1 = require("./constants"); const EMPTY = "0x"; /** * Checks if address is a valid ethereum address and normalizes so it can be used by both subgraph and web3. * @param address * @returns The normalized address. */ const normalizeAddress = (address) => { if (!address) return ""; if (ethers_1.ethers.utils.isAddress(address) === false) { throw new SFError_1.SFError({ type: "INVALID_ADDRESS", message: "The address you have entered is not a valid ethereum address", }); } return address.toLowerCase(); }; exports.normalizeAddress = normalizeAddress; const isPermissionsClean = (permissions) => { return ((permissions & ~(constants_1.AUTHORIZE_FLOW_OPERATOR_CREATE | constants_1.AUTHORIZE_FLOW_OPERATOR_UPDATE | constants_1.AUTHORIZE_FLOW_OPERATOR_DELETE)) === 0); }; exports.isPermissionsClean = isPermissionsClean; const _addPermissions = (oldPermissions, permissionsDelta) => { return oldPermissions | permissionsDelta; }; exports._addPermissions = _addPermissions; const _removePermissions = (oldPermissions, permissionsDelta) => { return oldPermissions & ~permissionsDelta; }; exports._removePermissions = _removePermissions; const isNullOrEmpty = (str) => { return str == null || str === ""; }; exports.isNullOrEmpty = isNullOrEmpty; function toBN(num) { return ethers_1.ethers.BigNumber.from(num); } /** * Removes the 8-character (4 byte) signature hash from `callData`. * @param callData * @returns function parameters */ const removeSigHashFromCallData = (callData) => EMPTY.concat(callData.slice(10)); exports.removeSigHashFromCallData = removeSigHashFromCallData; /** * A wrapper function for getting the ethers TransactionDescription object given fragments (e.g. ABI), callData and the value amount sent. * @param fragments ABI * @param data callData of a function * @param value amount of ether sent * @returns ethers.TransactionDescription object */ const getTransactionDescription = (fragments, data, value) => { const iface = new ethers_1.ethers.utils.Interface(fragments); const txnDescription = iface.parseTransaction({ data, value }); return txnDescription; }; exports.getTransactionDescription = getTransactionDescription; /** * Gets the per second flow rate given an `amountPerYear` value. * @param amountPerYear the amount you want to stream per year * @returns flow rate per second */ const getPerSecondFlowRateByYear = (amountPerYear) => { return Math.round((Number(amountPerYear) / constants_1.YEAR_IN_SECONDS) * constants_1.BASE_18).toString(); }; exports.getPerSecondFlowRateByYear = getPerSecondFlowRateByYear; /** * Gets the per second flow rate given an `amountPerMonth` value. * @param amountPerMonth the amount you want to stream per month * @returns flow rate per second */ const getPerSecondFlowRateByMonth = (amountPerMonth) => { return Math.round((Number(amountPerMonth) / constants_1.MONTH_IN_SECONDS) * constants_1.BASE_18).toString(); }; exports.getPerSecondFlowRateByMonth = getPerSecondFlowRateByMonth; /** * Gets the per second flow rate given an `amountPerWeek` value. * @param amountPerWeek the amount you want to stream per Week * @returns flow rate per second */ const getPerSecondFlowRateByWeek = (amountPerWeek) => { return Math.round((Number(amountPerWeek) / constants_1.WEEK_IN_SECONDS) * constants_1.BASE_18).toString(); }; exports.getPerSecondFlowRateByWeek = getPerSecondFlowRateByWeek; /** * Gets the per second flow rate given an `amountPerDay` value. * @param amountPerDay the amount you want to stream per day * @returns flow rate per second */ const getPerSecondFlowRateByDay = (amountPerDay) => { return Math.round((Number(amountPerDay) / constants_1.DAY_IN_SECONDS) * constants_1.BASE_18).toString(); }; exports.getPerSecondFlowRateByDay = getPerSecondFlowRateByDay; /** * Gets daily, weekly, monthly and yearly flowed amounts given a per second flow rate. * @param perSecondFlowRate * @returns */ const getFlowAmountByPerSecondFlowRate = (perSecondFlowRate) => { const decimalFlowRate = Number(perSecondFlowRate) / constants_1.BASE_18; return { daily: Math.round(decimalFlowRate * constants_1.DAY_IN_SECONDS).toString(), weekly: Math.round(decimalFlowRate * constants_1.WEEK_IN_SECONDS).toString(), monthly: Math.round(decimalFlowRate * constants_1.MONTH_IN_SECONDS).toString(), yearly: Math.round(decimalFlowRate * constants_1.YEAR_IN_SECONDS).toString(), }; }; exports.getFlowAmountByPerSecondFlowRate = getFlowAmountByPerSecondFlowRate; /** * The formula for calculating the flowed amount since updated using Subgraph data. * @param netFlowRate the net flow rate of the user * @param currentTimestamp the current timestamp * @param updatedAtTimestamp the updated at timestamp of the `AccountTokenSnapshot` entity * @returns the flowed amount since the updatedAt timestamp */ const flowedAmountSinceUpdatedAt = ({ netFlowRate, currentTimestamp, updatedAtTimestamp, }) => { return toBN(currentTimestamp) .sub(toBN(updatedAtTimestamp)) .mul(toBN(netFlowRate)); }; exports.flowedAmountSinceUpdatedAt = flowedAmountSinceUpdatedAt; /** * The formula for calculating the total amount distributed to the subscriber (pending or received). * @param indexSubscriptions the index subscriptions of a single token from an account. * @returns the total amount received since updated at (both pending and actually distributed) */ const subscriptionTotalAmountDistributedSinceUpdated = (indexSubscriptions) => { return indexSubscriptions.reduce((x, y) => toBN(x) .add(toBN(y.index.indexValue).sub(toBN(y.indexValueUntilUpdatedAt))) .mul(toBN(y.units)), toBN(0)); }; exports.subscriptionTotalAmountDistributedSinceUpdated = subscriptionTotalAmountDistributedSinceUpdated; /** * The formula for calculating the total amount received (approved subscriptions). * @param indexSubscriptions the index subscriptions of a single token from an account. * @returns the total amount received since updated at (actually distributed into wallet) */ const subscriptionTotalAmountReceivedSinceUpdated = (indexSubscriptions) => { return indexSubscriptions .filter((x) => x.approved) .reduce((x, y) => toBN(x) .add(toBN(y.index.indexValue).sub(toBN(y.indexValueUntilUpdatedAt))) .mul(toBN(y.units)), toBN(0)); }; exports.subscriptionTotalAmountReceivedSinceUpdated = subscriptionTotalAmountReceivedSinceUpdated; /** * The formula for calculating the total amount that is claimable. * @param indexSubscriptions the index subscriptions of a single token from an account. * @returns the total amount that can be claimed since updated at */ const subscriptionTotalAmountClaimableSinceUpdatedAt = (indexSubscriptions) => { return (0, exports.subscriptionTotalAmountDistributedSinceUpdated)(indexSubscriptions).sub((0, exports.subscriptionTotalAmountReceivedSinceUpdated)(indexSubscriptions)); }; exports.subscriptionTotalAmountClaimableSinceUpdatedAt = subscriptionTotalAmountClaimableSinceUpdatedAt; const getStringCurrentTimeInSeconds = () => Math.floor(new Date().getTime() / 1000); exports.getStringCurrentTimeInSeconds = getStringCurrentTimeInSeconds; const getSanitizedTimestamp = (timestamp) => new Date(Number(timestamp.toString()) * 1000); exports.getSanitizedTimestamp = getSanitizedTimestamp; /** * The formula for calculating the balance until updated at of a user (claimable + received tokens from index) * @param currentBalance the current balance until updated at from the `AccountTokenSnapshot` entity * @param netFlowRate the net flow rate of the user * @param currentTimestamp the current timestamp * @param updatedAtTimestamp the updated at timestamp of the `AccountTokenSnapshot` entity * @returns the balance since the updated at timestamp */ const calculateAvailableBalance = ({ currentBalance, netFlowRate, currentTimestamp, updatedAtTimestamp, indexSubscriptions, }) => { return toBN(currentBalance) .add((0, exports.flowedAmountSinceUpdatedAt)({ netFlowRate, currentTimestamp, updatedAtTimestamp, })) .add((0, exports.subscriptionTotalAmountReceivedSinceUpdated)(indexSubscriptions)); }; exports.calculateAvailableBalance = calculateAvailableBalance; // NOTE: This is the only places we are allowed to use explicit any in the // sdk-core otherwise this doesn't work properly. const isEthersProvider = (provider) => !!provider.getNetwork; exports.isEthersProvider = isEthersProvider; const isInjectedWeb3 = (provider) => !!provider.currentProvider; exports.isInjectedWeb3 = isInjectedWeb3; const isInjectedEthers = (provider) => !!provider.provider; exports.isInjectedEthers = isInjectedEthers; /** * Why? Because `return obj as T` and `return <T>obj` are not safe type casts. */ const typeGuard = (obj) => obj; exports.typeGuard = typeGuard; const getFlowOperatorId = (sender, flowOperator) => { const encoder = ethers_1.ethers.utils.defaultAbiCoder; const encodedData = encoder.encode(["string", "address", "address"], ["flowOperator", sender, flowOperator]); return ethers_1.ethers.utils.keccak256(encodedData); }; exports.getFlowOperatorId = getFlowOperatorId; /** * Applies clipping to deposit (based on contracts clipping logic) * @param deposit the deposit to clip * @param roundingDown whether to round up or down * @returns clipped deposit */ const clipDepositNumber = (deposit, roundingDown = false) => { // last 32 bits of the deposit (96 bits) is clipped off const rounding = roundingDown ? 0 : deposit.and(toBN(0xffffffff)).isZero() ? 0 : 1; return deposit.shr(32).add(toBN(rounding)).shl(32); }; exports.clipDepositNumber = clipDepositNumber; async function tryGet(somePromise, defaultReturnValue) { try { return await somePromise; } catch { return defaultReturnValue; } } //# sourceMappingURL=utils.js.map