2022-04-27 02:52:23 +04:00
import logger from '../../logger' ;
import DB from '../../database' ;
class NodesApi {
2022-04-29 03:57:27 +04:00
public async $getNode ( public_key : string ) : Promise < any > {
try {
2022-07-12 20:18:41 +02:00
const query = `
2022-07-12 21:28:02 +02:00
SELECT nodes . * , geo_names_as . names as as_organization , geo_names_city . names as city ,
geo_names_country . names as country , geo_names_subdivision . names as subdivision ,
2022-07-12 20:18:41 +02:00
( SELECT Count ( * )
FROM channels
WHERE channels . status < 2 AND ( channels . node1_public_key = ? OR channels . node2_public_key = ? ) ) AS channel_count ,
( SELECT Sum ( capacity )
FROM channels
WHERE channels . status < 2 AND ( channels . node1_public_key = ? OR channels . node2_public_key = ? ) ) AS capacity ,
( SELECT Avg ( capacity )
FROM channels
WHERE status < 2 AND ( node1_public_key = ? OR node2_public_key = ? ) ) AS channels_capacity_avg
FROM nodes
2022-07-12 21:07:38 +02:00
LEFT JOIN geo_names geo_names_as on geo_names_as . id = as_number
LEFT JOIN geo_names geo_names_city on geo_names_city . id = city_id
2022-07-12 21:28:02 +02:00
LEFT JOIN geo_names geo_names_subdivision on geo_names_subdivision . id = subdivision_id
2022-07-12 21:07:38 +02:00
LEFT JOIN geo_names geo_names_country on geo_names_country . id = country_id
2022-07-12 20:18:41 +02:00
WHERE public_key = ?
` ;
2022-05-15 16:48:38 +04:00
const [ rows ] : any = await DB . query ( query , [ public_key , public_key , public_key , public_key , public_key , public_key , public_key ] ) ;
2022-07-12 21:07:38 +02:00
if ( rows . length > 0 ) {
rows [ 0 ] . as_organization = JSON . parse ( rows [ 0 ] . as_organization ) ;
2022-07-12 21:28:02 +02:00
rows [ 0 ] . subdivision = JSON . parse ( rows [ 0 ] . subdivision ) ;
2022-07-12 21:07:38 +02:00
rows [ 0 ] . city = JSON . parse ( rows [ 0 ] . city ) ;
rows [ 0 ] . country = JSON . parse ( rows [ 0 ] . country ) ;
return rows [ 0 ] ;
}
return null ;
2022-04-29 03:57:27 +04:00
} catch ( e ) {
logger . err ( '$getNode error: ' + ( e instanceof Error ? e.message : e ) ) ;
throw e ;
}
}
2022-07-11 17:52:38 +02:00
public async $getAllNodes ( ) : Promise < any > {
try {
const query = ` SELECT * FROM nodes ` ;
const [ rows ] : any = await DB . query ( query ) ;
return rows ;
} catch ( e ) {
logger . err ( '$getAllNodes error: ' + ( e instanceof Error ? e.message : e ) ) ;
throw e ;
}
}
2022-05-05 23:19:24 +04:00
public async $getNodeStats ( public_key : string ) : Promise < any > {
try {
2022-07-02 16:46:57 +02:00
const query = ` SELECT UNIX_TIMESTAMP(added) AS added, capacity, channels FROM node_stats WHERE public_key = ? ORDER BY added DESC ` ;
2022-05-05 23:19:24 +04:00
const [ rows ] : any = await DB . query ( query , [ public_key ] ) ;
return rows ;
} catch ( e ) {
logger . err ( '$getNodeStats error: ' + ( e instanceof Error ? e.message : e ) ) ;
throw e ;
}
}
2022-04-27 02:52:23 +04:00
public async $getTopCapacityNodes ( ) : Promise < any > {
try {
2022-05-08 16:16:54 +04:00
const query = ` SELECT nodes.*, node_stats.capacity, node_stats.channels FROM nodes LEFT JOIN node_stats ON node_stats.public_key = nodes.public_key ORDER BY node_stats.added DESC, node_stats.capacity DESC LIMIT 10 ` ;
2022-04-27 02:52:23 +04:00
const [ rows ] : any = await DB . query ( query ) ;
return rows ;
} catch ( e ) {
logger . err ( '$getTopCapacityNodes error: ' + ( e instanceof Error ? e.message : e ) ) ;
throw e ;
}
}
public async $getTopChannelsNodes ( ) : Promise < any > {
try {
2022-05-08 16:16:54 +04:00
const query = ` SELECT nodes.*, node_stats.capacity, node_stats.channels FROM nodes LEFT JOIN node_stats ON node_stats.public_key = nodes.public_key ORDER BY node_stats.added DESC, node_stats.channels DESC LIMIT 10 ` ;
2022-04-27 02:52:23 +04:00
const [ rows ] : any = await DB . query ( query ) ;
return rows ;
} catch ( e ) {
logger . err ( '$getTopChannelsNodes error: ' + ( e instanceof Error ? e.message : e ) ) ;
throw e ;
}
}
2022-05-09 18:21:42 +04:00
public async $searchNodeByPublicKeyOrAlias ( search : string ) {
try {
const searchStripped = search . replace ( '%' , '' ) + '%' ;
2022-05-15 19:22:14 +04:00
const query = ` SELECT nodes.public_key, nodes.alias, node_stats.capacity FROM nodes LEFT JOIN node_stats ON node_stats.public_key = nodes.public_key WHERE nodes.public_key LIKE ? OR nodes.alias LIKE ? GROUP BY nodes.public_key ORDER BY node_stats.capacity DESC LIMIT 10 ` ;
2022-05-09 18:21:42 +04:00
const [ rows ] : any = await DB . query ( query , [ searchStripped , searchStripped ] ) ;
return rows ;
} catch ( e ) {
logger . err ( '$searchNodeByPublicKeyOrAlias error: ' + ( e instanceof Error ? e.message : e ) ) ;
throw e ;
}
}
2022-07-12 22:32:13 +02:00
public async $getNodesAsShare() {
try {
2022-07-16 11:32:48 +02:00
let query = ` SELECT names, COUNT(DISTINCT nodes.public_key) as nodesCount, SUM(capacity) as capacity
FROM nodes
2022-07-12 22:32:13 +02:00
JOIN geo_names ON geo_names . id = nodes . as_number
2022-07-16 11:32:48 +02:00
JOIN channels ON channels . node1_public_key = nodes . public_key OR channels . node2_public_key = nodes . public_key
2022-07-12 22:32:13 +02:00
GROUP BY as_number
2022-07-16 11:32:48 +02:00
ORDER BY COUNT ( DISTINCT nodes . public_key ) DESC
2022-07-12 22:32:13 +02:00
` ;
const [ nodesCountPerAS ] : any = await DB . query ( query ) ;
query = ` SELECT COUNT(*) as total FROM nodes WHERE as_number IS NOT NULL ` ;
const [ nodesWithAS ] : any = await DB . query ( query ) ;
const nodesPerAs : any [ ] = [ ] ;
for ( const as of nodesCountPerAS ) {
nodesPerAs . push ( {
name : JSON.parse ( as . names ) ,
count : as.nodesCount ,
share : Math.floor ( as . nodesCount / nodesWithAS [ 0 ] . total * 10000 ) / 100 ,
2022-07-16 11:32:48 +02:00
capacity : as.capacity ,
2022-07-12 22:32:13 +02:00
} )
}
return nodesPerAs ;
} catch ( e ) {
logger . err ( ` Cannot get nodes grouped by AS. Reason: ${ e instanceof Error ? e.message : e } ` ) ;
throw e ;
}
}
2022-07-13 00:25:40 +02:00
public async $getNodesPerCountry ( country : string ) {
try {
2022-07-16 15:56:36 +02:00
const query = `
SELECT node_stats . public_key , node_stats . capacity , node_stats . channels , nodes . alias ,
UNIX_TIMESTAMP ( nodes . first_seen ) as first_seen , UNIX_TIMESTAMP ( nodes . updated_at ) as updated_at ,
geo_names_city . names as city
FROM node_stats
JOIN (
SELECT public_key , MAX ( added ) as last_added
FROM node_stats
GROUP BY public_key
) as b ON b . public_key = node_stats . public_key AND b . last_added = node_stats . added
LEFT JOIN nodes ON nodes . public_key = node_stats . public_key
LEFT JOIN geo_names geo_names_country ON geo_names_country . id = nodes . country_id
LEFT JOIN geo_names geo_names_city ON geo_names_city . id = nodes . city_id
WHERE LOWER ( JSON_EXTRACT ( geo_names_country . names , '$.en' ) ) = ?
ORDER BY capacity DESC
2022-07-13 00:25:40 +02:00
` ;
const [ rows ] : any = await DB . query ( query , [ ` " ${ country } " ` ] ) ;
2022-07-16 15:56:36 +02:00
for ( let i = 0 ; i < rows . length ; ++ i ) {
rows [ i ] . city = JSON . parse ( rows [ i ] . city ) ;
}
2022-07-13 00:25:40 +02:00
return rows ;
} catch ( e ) {
logger . err ( ` Cannot get nodes for country ${ country } . Reason: ${ e instanceof Error ? e.message : e } ` ) ;
throw e ;
}
}
2022-04-27 02:52:23 +04:00
}
export default new NodesApi ( ) ;