web/storagenode: months online calculations changed
Change-Id: I01d0ab5f9929a8cf2fca81adef43d9c979a18118
This commit is contained in:
parent
c272872d5d
commit
18914e4d1a
@ -2,6 +2,7 @@
|
|||||||
// See LICENSE for copying information.
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
import { Duration, millisecondsInSecond, secondsInMinute } from '@/app/utils/duration';
|
import { Duration, millisecondsInSecond, secondsInMinute } from '@/app/utils/duration';
|
||||||
|
import { getMonthsBeforeNow } from '@/app/utils/payout';
|
||||||
import { SNOApi } from '@/storagenode/api/storagenode';
|
import { SNOApi } from '@/storagenode/api/storagenode';
|
||||||
import { Dashboard, SatelliteInfo } from '@/storagenode/dashboard';
|
import { Dashboard, SatelliteInfo } from '@/storagenode/dashboard';
|
||||||
import { BandwidthUsed, EgressUsed, IngressUsed, Satellite, Satellites, Stamp } from '@/storagenode/satellite';
|
import { BandwidthUsed, EgressUsed, IngressUsed, Satellite, Satellites, Stamp } from '@/storagenode/satellite';
|
||||||
@ -155,11 +156,7 @@ export function makeNodeModule(api: SNOApi) {
|
|||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
monthsOnNetwork: (state): number => {
|
monthsOnNetwork: (state): number => {
|
||||||
const now = new Date();
|
return getMonthsBeforeNow(state.selectedSatellite.joinDate);
|
||||||
const secondsInMonthApproximately = 2628000;
|
|
||||||
const differenceInSeconds = (now.getTime() - state.selectedSatellite.joinDate.getTime()) / 1000;
|
|
||||||
|
|
||||||
return Math.ceil(differenceInSeconds / secondsInMonthApproximately);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
33
web/storagenode/src/app/utils/payout.ts
Normal file
33
web/storagenode/src/app/utils/payout.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
// Copyright (C) 2020 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
// TODO: functions should be moved to related business logic layer
|
||||||
|
/**
|
||||||
|
* Returns held percentage depends on number of months that node is online.
|
||||||
|
* @param startedAt date since node is online.
|
||||||
|
*/
|
||||||
|
export function getHeldPercentage(startedAt: Date): number {
|
||||||
|
const monthsOnline = getMonthsBeforeNow(startedAt);
|
||||||
|
|
||||||
|
switch (true) {
|
||||||
|
case monthsOnline < 4:
|
||||||
|
return 75;
|
||||||
|
case monthsOnline < 7:
|
||||||
|
return 50;
|
||||||
|
case monthsOnline < 10:
|
||||||
|
return 25;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns number of months passes till now.
|
||||||
|
* @param startedAt date since node is online.
|
||||||
|
*/
|
||||||
|
export function getMonthsBeforeNow(startedAt: Date): number {
|
||||||
|
const now = new Date();
|
||||||
|
const yearsDiff = now.getUTCFullYear() - startedAt.getUTCFullYear();
|
||||||
|
|
||||||
|
return (yearsDiff * 12) + (now.getUTCMonth() - startedAt.getUTCMonth()) + 1;
|
||||||
|
}
|
4
web/storagenode/tests/typings.d.ts
vendored
Normal file
4
web/storagenode/tests/typings.d.ts
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
// Copyright (C) 2020 Storj Labs, Inc.
|
||||||
|
// See LICENSE for copying information.
|
||||||
|
|
||||||
|
declare var global: any;
|
@ -283,23 +283,8 @@ describe('actions', () => {
|
|||||||
|
|
||||||
describe('getters', () => {
|
describe('getters', () => {
|
||||||
it('getter monthsOnNetwork returns correct value', () => {
|
it('getter monthsOnNetwork returns correct value', () => {
|
||||||
const dashboardInfo = new Dashboard(
|
const _Date = Date;
|
||||||
'1',
|
const testJoinAt = new Date(Date.UTC(2020, 0, 30));
|
||||||
'2',
|
|
||||||
[
|
|
||||||
new SatelliteInfo('3', 'url1', null, null),
|
|
||||||
new SatelliteInfo('4', 'url2', new Date(2020, 1, 1), new Date(2020, 0, 1)),
|
|
||||||
],
|
|
||||||
new DiskSpaceInfo(99, 100, 4),
|
|
||||||
new BandwidthInfo(50),
|
|
||||||
new Date(),
|
|
||||||
new Date(2019, 3, 1),
|
|
||||||
'0.1.1',
|
|
||||||
'0.2.2',
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
const now = new Date();
|
|
||||||
const testJoinAt = new Date(now.getTime() - 1000000);
|
|
||||||
|
|
||||||
const satelliteInfo = new Satellite(
|
const satelliteInfo = new Satellite(
|
||||||
'3',
|
'3',
|
||||||
@ -316,15 +301,39 @@ describe('getters', () => {
|
|||||||
testJoinAt,
|
testJoinAt,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const firstTestDate = new Date(2020, 1, 1);
|
||||||
|
const secondTestDate = new Date(Date.UTC(2019, 10, 29));
|
||||||
|
|
||||||
|
const mockedDate = new Date(1580522290000);
|
||||||
|
global.Date = jest.fn(() => mockedDate); // Sat Feb 01 2020
|
||||||
|
|
||||||
|
const dashboardInfo = new Dashboard(
|
||||||
|
'1',
|
||||||
|
'2',
|
||||||
|
[
|
||||||
|
new SatelliteInfo('3', 'url1', null, null),
|
||||||
|
new SatelliteInfo('4', 'url2', firstTestDate, new Date(2020, 0, 1)),
|
||||||
|
],
|
||||||
|
new DiskSpaceInfo(99, 100, 4),
|
||||||
|
new BandwidthInfo(50),
|
||||||
|
new Date(),
|
||||||
|
firstTestDate,
|
||||||
|
'0.1.1',
|
||||||
|
'0.2.2',
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
store.commit(NODE_MUTATIONS.POPULATE_STORE, dashboardInfo);
|
store.commit(NODE_MUTATIONS.POPULATE_STORE, dashboardInfo);
|
||||||
store.commit(NODE_MUTATIONS.SELECT_SATELLITE, satelliteInfo);
|
store.commit(NODE_MUTATIONS.SELECT_SATELLITE, satelliteInfo);
|
||||||
|
|
||||||
expect(store.getters.monthsOnNetwork).toBe(1);
|
expect(store.getters.monthsOnNetwork).toBe(2);
|
||||||
|
|
||||||
satelliteInfo.joinDate = new Date(testJoinAt.getTime() - 9e9);
|
satelliteInfo.joinDate = secondTestDate;
|
||||||
|
|
||||||
store.commit(NODE_MUTATIONS.SELECT_SATELLITE, satelliteInfo);
|
store.commit(NODE_MUTATIONS.SELECT_SATELLITE, satelliteInfo);
|
||||||
|
|
||||||
expect(store.getters.monthsOnNetwork).toBe(4);
|
expect(store.getters.monthsOnNetwork).toBe(4);
|
||||||
|
|
||||||
|
global.Date = _Date;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -4,8 +4,9 @@
|
|||||||
import Vuex from 'vuex';
|
import Vuex from 'vuex';
|
||||||
|
|
||||||
import { makeNodeModule } from '@/app/store/modules/node';
|
import { makeNodeModule } from '@/app/store/modules/node';
|
||||||
import { getHeldPercentage, makePayoutModule, PAYOUT_ACTIONS, PAYOUT_MUTATIONS } from '@/app/store/modules/payout';
|
import { makePayoutModule, PAYOUT_ACTIONS, PAYOUT_MUTATIONS } from '@/app/store/modules/payout';
|
||||||
import { HeldInfo, PayoutInfoRange, PayoutPeriod, TotalPayoutInfo } from '@/app/types/payout';
|
import { HeldInfo, PayoutInfoRange, PayoutPeriod, TotalPayoutInfo } from '@/app/types/payout';
|
||||||
|
import { getHeldPercentage, getMonthsBeforeNow } from '@/app/utils/payout';
|
||||||
import { PayoutHttpApi } from '@/storagenode/api/payout';
|
import { PayoutHttpApi } from '@/storagenode/api/payout';
|
||||||
import { SNOApi } from '@/storagenode/api/storagenode';
|
import { SNOApi } from '@/storagenode/api/storagenode';
|
||||||
import { createLocalVue } from '@vue/test-utils';
|
import { createLocalVue } from '@vue/test-utils';
|
||||||
@ -23,12 +24,12 @@ const store = new Vuex.Store({ modules: { payoutModule, node: nodeModule } });
|
|||||||
|
|
||||||
const state = store.state as any;
|
const state = store.state as any;
|
||||||
|
|
||||||
describe('mutations', () => {
|
describe('mutations', (): void => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createLocalVue().use(Vuex);
|
createLocalVue().use(Vuex);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets held information', () => {
|
it('sets held information', (): void => {
|
||||||
const heldInfo = new HeldInfo(13, 12, 11);
|
const heldInfo = new HeldInfo(13, 12, 11);
|
||||||
|
|
||||||
store.commit(PAYOUT_MUTATIONS.SET_HELD_INFO, heldInfo);
|
store.commit(PAYOUT_MUTATIONS.SET_HELD_INFO, heldInfo);
|
||||||
@ -38,7 +39,7 @@ describe('mutations', () => {
|
|||||||
expect(state.payoutModule.heldInfo.usagePut).toBe(11);
|
expect(state.payoutModule.heldInfo.usagePut).toBe(11);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets total payout information', () => {
|
it('sets total payout information', (): void => {
|
||||||
const totalInfo = new TotalPayoutInfo(50, 100, 22);
|
const totalInfo = new TotalPayoutInfo(50, 100, 22);
|
||||||
|
|
||||||
store.commit(PAYOUT_MUTATIONS.SET_TOTAL, totalInfo);
|
store.commit(PAYOUT_MUTATIONS.SET_TOTAL, totalInfo);
|
||||||
@ -48,7 +49,7 @@ describe('mutations', () => {
|
|||||||
expect(state.payoutModule.currentMonthEarnings).toBe(22);
|
expect(state.payoutModule.currentMonthEarnings).toBe(22);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets period range', () => {
|
it('sets period range', (): void => {
|
||||||
const range = new PayoutInfoRange(new PayoutPeriod(2019, 2), new PayoutPeriod(2020, 3));
|
const range = new PayoutInfoRange(new PayoutPeriod(2019, 2), new PayoutPeriod(2020, 3));
|
||||||
|
|
||||||
store.commit(PAYOUT_MUTATIONS.SET_RANGE, range);
|
store.commit(PAYOUT_MUTATIONS.SET_RANGE, range);
|
||||||
@ -61,7 +62,7 @@ describe('mutations', () => {
|
|||||||
expect(state.payoutModule.periodRange.end.period).toBe('2020-04');
|
expect(state.payoutModule.periodRange.end.period).toBe('2020-04');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('sets held percentage', () => {
|
it('sets held percentage', (): void => {
|
||||||
const expectedHeldPercentage = 75;
|
const expectedHeldPercentage = 75;
|
||||||
|
|
||||||
store.commit(PAYOUT_MUTATIONS.SET_HELD_PERCENT, expectedHeldPercentage);
|
store.commit(PAYOUT_MUTATIONS.SET_HELD_PERCENT, expectedHeldPercentage);
|
||||||
@ -75,7 +76,7 @@ describe('actions', () => {
|
|||||||
jest.resetAllMocks();
|
jest.resetAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('success get held info by month', async () => {
|
it('success get held info by month', async (): Promise<void> => {
|
||||||
jest.spyOn(payoutApi, 'getHeldInfoByMonth').mockReturnValue(
|
jest.spyOn(payoutApi, 'getHeldInfoByMonth').mockReturnValue(
|
||||||
Promise.resolve(new HeldInfo(1, 2 , 3, 4, 5)),
|
Promise.resolve(new HeldInfo(1, 2 , 3, 4, 5)),
|
||||||
);
|
);
|
||||||
@ -91,7 +92,7 @@ describe('actions', () => {
|
|||||||
expect(state.payoutModule.heldPercentage).toBe(getHeldPercentage(new Date()));
|
expect(state.payoutModule.heldPercentage).toBe(getHeldPercentage(new Date()));
|
||||||
});
|
});
|
||||||
|
|
||||||
it('get held info by month throws an error when api call fails', async () => {
|
it('get held info by month throws an error when api call fails', async (): Promise<void> => {
|
||||||
jest.spyOn(payoutApi, 'getHeldInfoByMonth').mockImplementation(() => { throw new Error(); });
|
jest.spyOn(payoutApi, 'getHeldInfoByMonth').mockImplementation(() => { throw new Error(); });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -103,7 +104,7 @@ describe('actions', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('success get held info by period', async () => {
|
it('success get held info by period', async (): Promise<void> => {
|
||||||
jest.spyOn(payoutApi, 'getHeldInfoByPeriod').mockReturnValue(
|
jest.spyOn(payoutApi, 'getHeldInfoByPeriod').mockReturnValue(
|
||||||
Promise.resolve(new HeldInfo(1, 2 , 3, 4, 5)),
|
Promise.resolve(new HeldInfo(1, 2 , 3, 4, 5)),
|
||||||
);
|
);
|
||||||
@ -118,7 +119,7 @@ describe('actions', () => {
|
|||||||
expect(state.payoutModule.heldInfo.held).toBe(0);
|
expect(state.payoutModule.heldInfo.held).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('get held info by period throws an error when api call fails', async () => {
|
it('get held info by period throws an error when api call fails', async (): Promise<void> => {
|
||||||
jest.spyOn(payoutApi, 'getHeldInfoByPeriod').mockImplementation(() => { throw new Error(); });
|
jest.spyOn(payoutApi, 'getHeldInfoByPeriod').mockImplementation(() => { throw new Error(); });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -130,7 +131,7 @@ describe('actions', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('success get total', async () => {
|
it('success get total', async (): Promise<void> => {
|
||||||
jest.spyOn(payoutApi, 'getTotal').mockReturnValue(
|
jest.spyOn(payoutApi, 'getTotal').mockReturnValue(
|
||||||
Promise.resolve(new TotalPayoutInfo(10, 20, 5)),
|
Promise.resolve(new TotalPayoutInfo(10, 20, 5)),
|
||||||
);
|
);
|
||||||
@ -142,7 +143,7 @@ describe('actions', () => {
|
|||||||
expect(state.payoutModule.currentMonthEarnings).toBe(0);
|
expect(state.payoutModule.currentMonthEarnings).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('get total throws an error when api call fails', async () => {
|
it('get total throws an error when api call fails', async (): Promise<void> => {
|
||||||
jest.spyOn(payoutApi, 'getTotal').mockImplementation(() => { throw new Error(); });
|
jest.spyOn(payoutApi, 'getTotal').mockImplementation(() => { throw new Error(); });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -155,7 +156,7 @@ describe('actions', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
it('success sets period range', async () => {
|
it('success sets period range', async (): Promise<void> => {
|
||||||
await store.dispatch(
|
await store.dispatch(
|
||||||
PAYOUT_ACTIONS.SET_PERIODS_RANGE,
|
PAYOUT_ACTIONS.SET_PERIODS_RANGE,
|
||||||
new PayoutInfoRange(
|
new PayoutInfoRange(
|
||||||
@ -169,17 +170,53 @@ describe('actions', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('utils functions', () => {
|
describe('utils functions', (): void => {
|
||||||
it('get correct help percentage', () => {
|
const _Date = Date;
|
||||||
const nowTime = new Date().getTime();
|
|
||||||
const testDifferencesInMilliseconds: number[] = [5e9, 1.4e10, 2.3e10, 4e10];
|
// TODO: investigate reset mocks in config
|
||||||
|
beforeEach(() => {
|
||||||
|
jest.resetAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
global.Date = _Date;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('get correct held percentage', (): void => {
|
||||||
|
const testDates: Date[] = [
|
||||||
|
new Date(Date.UTC(2020, 0, 30)),
|
||||||
|
new Date(Date.UTC(2019, 10, 29)),
|
||||||
|
new Date(Date.UTC(2019, 7, 24)),
|
||||||
|
new Date(Date.UTC(2018, 1, 24)),
|
||||||
|
];
|
||||||
const expectedHeldPercentages: number[] = [75, 50, 25, 0];
|
const expectedHeldPercentages: number[] = [75, 50, 25, 0];
|
||||||
|
|
||||||
for (let i = 0; i < testDifferencesInMilliseconds.length; i++) {
|
const mockedDate = new Date(1580522290000); // Sat Feb 01 2020
|
||||||
const date = new Date(nowTime - testDifferencesInMilliseconds[i]);
|
global.Date = jest.fn(() => mockedDate);
|
||||||
const heldPercentage = getHeldPercentage(date);
|
|
||||||
|
for (let i = 0; i < testDates.length; i++) {
|
||||||
|
const heldPercentage = getHeldPercentage(testDates[i]);
|
||||||
|
|
||||||
expect(heldPercentage).toBe(expectedHeldPercentages[i]);
|
expect(heldPercentage).toBe(expectedHeldPercentages[i]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('get correct months difference', (): void => {
|
||||||
|
const testDates: Date[] = [
|
||||||
|
new Date(Date.UTC(2020, 0, 30)),
|
||||||
|
new Date(Date.UTC(2019, 10, 29)),
|
||||||
|
new Date(Date.UTC(2019, 7, 24)),
|
||||||
|
new Date(Date.UTC(2018, 1, 24)),
|
||||||
|
];
|
||||||
|
const expectedMonthsCount: number[] = [2, 4, 7, 25];
|
||||||
|
|
||||||
|
const mockedDate = new Date(1580522290000); // Sat Feb 01 2020
|
||||||
|
global.Date = jest.fn(() => mockedDate);
|
||||||
|
|
||||||
|
for (let i = 0; i < testDates.length; i++) {
|
||||||
|
const heldPercentage = getMonthsBeforeNow(testDates[i]);
|
||||||
|
|
||||||
|
expect(heldPercentage).toBe(expectedMonthsCount[i]);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user