mirror of
https://github.com/apotdevin/thunderhub.git
synced 2025-02-22 06:21:37 +01:00
feat: add report queries
This commit is contained in:
parent
69f277f044
commit
dce5795fa8
9 changed files with 272 additions and 1 deletions
|
@ -24,13 +24,16 @@
|
|||
"@types/graphql-depth-limit": "^1.1.2",
|
||||
"@types/graphql-iso-date": "^3.3.3",
|
||||
"@types/node-fetch": "^2.5.3",
|
||||
"@types/underscore": "^1.9.4",
|
||||
"apollo-server": "^2.9.7",
|
||||
"date-fns": "^2.8.1",
|
||||
"dotenv": "^8.2.0",
|
||||
"graphql": "^14.5.8",
|
||||
"graphql-depth-limit": "^1.1.0",
|
||||
"graphql-iso-date": "^3.6.1",
|
||||
"graphql-rate-limit": "^2.0.1",
|
||||
"ln-service": "^46.6.0",
|
||||
"underscore": "^1.9.1",
|
||||
"winston": "^3.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
15
src/schemaTypes/query/report/ForwardChannels.ts
Normal file
15
src/schemaTypes/query/report/ForwardChannels.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { GraphQLObjectType, GraphQLString } from "graphql";
|
||||
|
||||
export const ForwardChannelsType = new GraphQLObjectType({
|
||||
name: "forwardChannelType",
|
||||
fields: () => {
|
||||
return {
|
||||
incoming: {
|
||||
type: GraphQLString
|
||||
},
|
||||
outgoing: {
|
||||
type: GraphQLString
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
|
@ -2,10 +2,12 @@ import { channelQueries } from "./channels";
|
|||
import { generalQueries } from "./general";
|
||||
import { invoiceQueries } from "./invoices";
|
||||
import { dataQueries } from "./data";
|
||||
import { reportQueries } from "./report";
|
||||
|
||||
export const query = {
|
||||
...channelQueries,
|
||||
...generalQueries,
|
||||
...invoiceQueries,
|
||||
...dataQueries
|
||||
...dataQueries,
|
||||
...reportQueries
|
||||
};
|
||||
|
|
58
src/schemas/query/report/ForwardChannels.ts
Normal file
58
src/schemas/query/report/ForwardChannels.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { GraphQLString } from "graphql";
|
||||
import { getForwards as getLnForwards } from "ln-service";
|
||||
import { logger } from "../../../helpers/logger";
|
||||
import { requestLimiter } from "../../../helpers/rateLimiter";
|
||||
import { subHours, subDays } from "date-fns";
|
||||
import { countArray } from "./Helpers";
|
||||
import { ForwardCompleteProps } from "./ForwardReport.interface";
|
||||
import { ForwardChannelsType } from "../../../schemaTypes/query/report/ForwardChannels";
|
||||
|
||||
export const getForwardChannelsReport = {
|
||||
type: ForwardChannelsType,
|
||||
args: {
|
||||
time: {
|
||||
type: GraphQLString
|
||||
}
|
||||
},
|
||||
resolve: async (root: any, params: any, context: any) => {
|
||||
await requestLimiter(
|
||||
context.ip,
|
||||
params,
|
||||
"getForwardChannelsReport",
|
||||
1,
|
||||
"1s"
|
||||
);
|
||||
const { lnd } = context;
|
||||
|
||||
let startDate = new Date();
|
||||
const endDate = new Date();
|
||||
|
||||
if (params.time === "month") {
|
||||
startDate = subDays(endDate, 30);
|
||||
} else if (params.time === "week") {
|
||||
startDate = subDays(endDate, 7);
|
||||
} else {
|
||||
startDate = subHours(endDate, 24);
|
||||
}
|
||||
|
||||
try {
|
||||
const forwardsList: ForwardCompleteProps = await getLnForwards({
|
||||
lnd: lnd,
|
||||
after: startDate,
|
||||
before: endDate,
|
||||
limit: 10000
|
||||
});
|
||||
|
||||
const incomingCount = countArray(forwardsList.forwards, true);
|
||||
const outgoingCount = countArray(forwardsList.forwards, false);
|
||||
|
||||
return {
|
||||
incoming: JSON.stringify(incomingCount),
|
||||
outgoing: JSON.stringify(outgoingCount)
|
||||
};
|
||||
} catch (error) {
|
||||
logger.error("Error getting forward channel report: %o", error);
|
||||
throw new Error("Failed to get forward channel report.");
|
||||
}
|
||||
}
|
||||
};
|
42
src/schemas/query/report/ForwardReport.interface.ts
Normal file
42
src/schemas/query/report/ForwardReport.interface.ts
Normal file
|
@ -0,0 +1,42 @@
|
|||
export interface ForwardProps {
|
||||
created_at: string;
|
||||
fee: number;
|
||||
fee_mtokens: string;
|
||||
incoming_channel: string;
|
||||
mtokens: string;
|
||||
outgoing_channel: string;
|
||||
tokens: number;
|
||||
}
|
||||
|
||||
export interface ForwardCompleteProps {
|
||||
forwards: ForwardProps[];
|
||||
next: string;
|
||||
}
|
||||
|
||||
export interface ListProps {
|
||||
[key: string]: ForwardProps[];
|
||||
}
|
||||
|
||||
export interface ReduceObjectProps {
|
||||
fee: number;
|
||||
tokens: number;
|
||||
}
|
||||
|
||||
export interface FinalProps {
|
||||
fee: number;
|
||||
tokens: number;
|
||||
amount: number;
|
||||
}
|
||||
|
||||
export interface FinalList {
|
||||
[key: string]: FinalProps;
|
||||
}
|
||||
|
||||
export interface CountProps {
|
||||
[key: string]: number;
|
||||
}
|
||||
|
||||
export interface ChannelCounts {
|
||||
name: string;
|
||||
count: number;
|
||||
}
|
71
src/schemas/query/report/ForwardReport.ts
Normal file
71
src/schemas/query/report/ForwardReport.ts
Normal file
|
@ -0,0 +1,71 @@
|
|||
import { GraphQLString } from "graphql";
|
||||
import { getForwards as getLnForwards } from "ln-service";
|
||||
import { logger } from "../../../helpers/logger";
|
||||
import { requestLimiter } from "../../../helpers/rateLimiter";
|
||||
import { groupBy } from "underscore";
|
||||
import {
|
||||
subHours,
|
||||
subDays,
|
||||
differenceInHours,
|
||||
differenceInCalendarDays
|
||||
} from "date-fns";
|
||||
import { reduceForwardArray } from "./Helpers";
|
||||
import { ForwardCompleteProps } from "./ForwardReport.interface";
|
||||
|
||||
export const getForwardReport = {
|
||||
type: GraphQLString,
|
||||
args: {
|
||||
time: {
|
||||
type: GraphQLString
|
||||
}
|
||||
},
|
||||
resolve: async (root: any, params: any, context: any) => {
|
||||
await requestLimiter(context.ip, params, "getForwardReport", 1, "1s");
|
||||
const { lnd } = context;
|
||||
|
||||
let startDate = new Date();
|
||||
const endDate = new Date();
|
||||
let days = 7;
|
||||
|
||||
if (params.time === "month") {
|
||||
startDate = subDays(endDate, 30);
|
||||
days = 30;
|
||||
} else if (params.time === "week") {
|
||||
startDate = subDays(endDate, 7);
|
||||
} else {
|
||||
startDate = subHours(endDate, 24);
|
||||
}
|
||||
|
||||
try {
|
||||
const forwardsList: ForwardCompleteProps = await getLnForwards({
|
||||
lnd: lnd,
|
||||
after: startDate,
|
||||
before: endDate,
|
||||
limit: 10000
|
||||
});
|
||||
|
||||
if (params.time === "month" || params.time === "week") {
|
||||
const orderedDay = groupBy(forwardsList.forwards, item => {
|
||||
return (
|
||||
days - differenceInCalendarDays(endDate, new Date(item.created_at))
|
||||
);
|
||||
});
|
||||
|
||||
const reducedOrderedDay = reduceForwardArray(orderedDay);
|
||||
|
||||
return JSON.stringify(reducedOrderedDay);
|
||||
} else {
|
||||
const orderedHour = groupBy(forwardsList.forwards, item => {
|
||||
return 24 - differenceInHours(endDate, new Date(item.created_at));
|
||||
});
|
||||
|
||||
const reducedOrderedHour = reduceForwardArray(orderedHour);
|
||||
|
||||
return JSON.stringify(reducedOrderedHour);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error("Error getting forward report: %o", error);
|
||||
throw new Error("Failed to get forward report.");
|
||||
}
|
||||
}
|
||||
};
|
58
src/schemas/query/report/Helpers.ts
Normal file
58
src/schemas/query/report/Helpers.ts
Normal file
|
@ -0,0 +1,58 @@
|
|||
import { reduce, sortBy } from "underscore";
|
||||
import {
|
||||
ForwardProps,
|
||||
ReduceObjectProps,
|
||||
FinalProps,
|
||||
FinalList,
|
||||
ListProps,
|
||||
CountProps,
|
||||
ChannelCounts
|
||||
} from "./ForwardReport.interface";
|
||||
|
||||
export const reduceForwardArray = (list: ListProps): FinalList => {
|
||||
let reducedOrder: FinalList = {};
|
||||
for (const key in list) {
|
||||
if (list.hasOwnProperty(key)) {
|
||||
const element: ForwardProps[] = list[key];
|
||||
const reducedArray: ReduceObjectProps = reduce(element, (a, b) => {
|
||||
return {
|
||||
fee: a.fee + b.fee,
|
||||
tokens: a.tokens + b.tokens
|
||||
};
|
||||
});
|
||||
reducedOrder[key] = {
|
||||
amount: element.length,
|
||||
...reducedArray
|
||||
} as FinalProps;
|
||||
}
|
||||
}
|
||||
|
||||
return reducedOrder;
|
||||
};
|
||||
|
||||
export const countArray = (
|
||||
list: ForwardProps[],
|
||||
type: boolean
|
||||
): ChannelCounts[] => {
|
||||
const count: CountProps = {};
|
||||
list
|
||||
.map(item => {
|
||||
return type ? item.incoming_channel : item.outgoing_channel;
|
||||
})
|
||||
.forEach(channel => {
|
||||
count[channel] = (count[channel] || 0) + 1;
|
||||
});
|
||||
|
||||
const mapped: ChannelCounts[] = [];
|
||||
for (const key in count) {
|
||||
if (count.hasOwnProperty(key)) {
|
||||
const element = count[key];
|
||||
mapped.push({
|
||||
name: key,
|
||||
count: element
|
||||
});
|
||||
}
|
||||
}
|
||||
sortBy(mapped, "count");
|
||||
return mapped;
|
||||
};
|
7
src/schemas/query/report/index.ts
Normal file
7
src/schemas/query/report/index.ts
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { getForwardReport } from "./ForwardReport";
|
||||
import { getForwardChannelsReport } from "./ForwardChannels";
|
||||
|
||||
export const reportQueries = {
|
||||
getForwardReport,
|
||||
getForwardChannelsReport
|
||||
};
|
15
yarn.lock
15
yarn.lock
|
@ -341,6 +341,11 @@
|
|||
dependencies:
|
||||
source-map "^0.6.1"
|
||||
|
||||
"@types/underscore@^1.9.4":
|
||||
version "1.9.4"
|
||||
resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.9.4.tgz#22d1a3e6b494608e430221ec085fa0b7ccee7f33"
|
||||
integrity sha512-CjHWEMECc2/UxOZh0kpiz3lEyX2Px3rQS9HzD20lxMvx571ivOBQKeLnqEjxUY0BMgp6WJWo/pQLRBwMW5v4WQ==
|
||||
|
||||
"@types/webpack-env@^1.14.1":
|
||||
version "1.14.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.14.1.tgz#0d8a53f308f017c53a5ddc3d07f4d6fa76b790d7"
|
||||
|
@ -1752,6 +1757,11 @@ dashdash@^1.12.0:
|
|||
dependencies:
|
||||
assert-plus "^1.0.0"
|
||||
|
||||
date-fns@^2.8.1:
|
||||
version "2.8.1"
|
||||
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.8.1.tgz#2109362ccb6c87c3ca011e9e31f702bc09e4123b"
|
||||
integrity sha512-EL/C8IHvYRwAHYgFRse4MGAPSqlJVlOrhVYZ75iQBKrnv+ZedmYsgwH3t+BCDuZDXpoo07+q9j4qgSSOa7irJg==
|
||||
|
||||
debug@2.6.9, debug@^2.2.0, debug@^2.3.3:
|
||||
version "2.6.9"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f"
|
||||
|
@ -5292,6 +5302,11 @@ typescript@^3.6.4:
|
|||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.2.tgz#27e489b95fa5909445e9fef5ee48d81697ad18fb"
|
||||
integrity sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==
|
||||
|
||||
underscore@^1.9.1:
|
||||
version "1.9.1"
|
||||
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961"
|
||||
integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==
|
||||
|
||||
union-value@^1.0.0:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847"
|
||||
|
|
Loading…
Add table
Reference in a new issue