Search API

This commit is contained in:
softsimon 2022-05-09 18:21:42 +04:00
parent caadae3f98
commit 1ed4c93b94
No known key found for this signature in database
GPG Key ID: 488D7DCFB5A430D7
7 changed files with 101 additions and 11 deletions

View File

@ -240,4 +240,9 @@ export class ApiService {
return this.httpClient.get<any[]>(this.apiBaseUrl + this.apiBasePath + '/lightning/api/v1/channels/txids/', { params }); return this.httpClient.get<any[]>(this.apiBaseUrl + this.apiBasePath + '/lightning/api/v1/channels/txids/', { params });
} }
lightningSearch$(searchText: string): Observable<any[]> {
let params = new HttpParams().set('searchText', searchText);
return this.httpClient.get<any[]>(this.apiBaseUrl + this.apiBasePath + '/lightning/api/v1/search', { params });
}
} }

View File

@ -13,6 +13,18 @@ class ChannelsApi {
} }
} }
public async $searchChannelsById(search: string): Promise<any[]> {
try {
const searchStripped = search.replace('%', '') + '%';
const query = `SELECT id, short_id, capacity FROM channels WHERE id LIKE ? OR short_id LIKE ? LIMIT 10`;
const [rows]: any = await DB.query(query, [searchStripped, searchStripped]);
return rows;
} catch (e) {
logger.err('$searchChannelsById error: ' + (e instanceof Error ? e.message : e));
throw e;
}
}
public async $getChannelsByStatus(status: number): Promise<any[]> { public async $getChannelsByStatus(status: number): Promise<any[]> {
try { try {
const query = `SELECT * FROM channels WHERE status = ?`; const query = `SELECT * FROM channels WHERE status = ?`;
@ -46,11 +58,12 @@ class ChannelsApi {
} }
} }
public async $getChannelByTransactionId(transactionId: string): Promise<any> { public async $getChannelsByTransactionId(transactionIds: string[]): Promise<any[]> {
try { try {
const query = `SELECT n1.alias AS alias_left, n2.alias AS alias_right, channels.* FROM channels LEFT JOIN nodes AS n1 ON n1.public_key = channels.node1_public_key LEFT JOIN nodes AS n2 ON n2.public_key = channels.node2_public_key WHERE channels.transaction_id = ?`; transactionIds = transactionIds.map((id) => '\'' + id + '\'');
const [rows]: any = await DB.query(query, [transactionId]); const query = `SELECT n1.alias AS alias_left, n2.alias AS alias_right, channels.* FROM channels LEFT JOIN nodes AS n1 ON n1.public_key = channels.node1_public_key LEFT JOIN nodes AS n2 ON n2.public_key = channels.node2_public_key WHERE channels.transaction_id IN (${transactionIds.join(', ')})`;
return rows[0]; const [rows]: any = await DB.query(query);
return rows;
} catch (e) { } catch (e) {
logger.err('$getChannelByTransactionId error: ' + (e instanceof Error ? e.message : e)); logger.err('$getChannelByTransactionId error: ' + (e instanceof Error ? e.message : e));
throw e; throw e;

View File

@ -8,11 +8,21 @@ class ChannelsRoutes {
public initRoutes(app: Express) { public initRoutes(app: Express) {
app app
.get(config.MEMPOOL.API_URL_PREFIX + 'channels/txids', this.$getChannelsByTransactionIds) .get(config.MEMPOOL.API_URL_PREFIX + 'channels/txids', this.$getChannelsByTransactionIds)
.get(config.MEMPOOL.API_URL_PREFIX + 'channels/search/:search', this.$searchChannelsById)
.get(config.MEMPOOL.API_URL_PREFIX + 'channels/:short_id', this.$getChannel) .get(config.MEMPOOL.API_URL_PREFIX + 'channels/:short_id', this.$getChannel)
.get(config.MEMPOOL.API_URL_PREFIX + 'channels', this.$getChannels) .get(config.MEMPOOL.API_URL_PREFIX + 'channels', this.$getChannels)
; ;
} }
private async $searchChannelsById(req: Request, res: Response) {
try {
const channels = await channelsApi.$searchChannelsById(req.params.search);
res.json(channels);
} catch (e) {
res.status(500).send(e instanceof Error ? e.message : e);
}
}
private async $getChannel(req: Request, res: Response) { private async $getChannel(req: Request, res: Response) {
try { try {
const channel = await channelsApi.$getChannel(req.params.short_id); const channel = await channelsApi.$getChannel(req.params.short_id);
@ -32,8 +42,8 @@ class ChannelsRoutes {
res.status(501).send('Missing parameter: public_key'); res.status(501).send('Missing parameter: public_key');
return; return;
} }
const channels = await channelsApi.$getChannelsForNode(req.query.public_key); const channels = await channelsApi.$getChannelsForNode(req.query.public_key);
res.json(channels); res.json(channels);
} catch (e) { } catch (e) {
res.status(500).send(e instanceof Error ? e.message : e); res.status(500).send(e instanceof Error ? e.message : e);
} }
@ -51,12 +61,18 @@ class ChannelsRoutes {
txIds.push(req.query.txId[_txId].toString()); txIds.push(req.query.txId[_txId].toString());
} }
} }
const channels: any[] = []; const channels = await channelsApi.$getChannelsByTransactionId(txIds);
for (const txId of txIds) { const result: any[] = [];
const channel = await channelsApi.$getChannelByTransactionId(txId); for (const txid of txIds) {
channels.push(channel); const foundChannel = channels.find((channel) => channel.transaction_id === txid);
if (foundChannel) {
result.push(foundChannel);
} else {
result.push(null);
}
} }
res.json(channels);
res.json(result);
} catch (e) { } catch (e) {
res.status(500).send(e instanceof Error ? e.message : e); res.status(500).send(e instanceof Error ? e.message : e);
} }

View File

@ -0,0 +1,32 @@
import config from '../../config';
import { Express, Request, Response } from 'express';
import nodesApi from './nodes.api';
import channelsApi from './channels.api';
class GeneralRoutes {
constructor() { }
public initRoutes(app: Express) {
app
.get(config.MEMPOOL.API_URL_PREFIX + 'search', this.$searchNodesAndChannels)
;
}
private async $searchNodesAndChannels(req: Request, res: Response) {
if (typeof req.query.searchText !== 'string') {
res.status(501).send('Missing parameter: searchText');
return;
}
try {
const nodes = await nodesApi.$searchNodeByPublicKeyOrAlias(req.query.searchText);
const channels = await channelsApi.$searchChannelsById(req.query.searchText);
res.json({
nodes: nodes,
channels: channels,
});
} catch (e) {
res.status(500).send(e instanceof Error ? e.message : e);
}
}
}
export default new GeneralRoutes();

View File

@ -59,6 +59,18 @@ class NodesApi {
throw e; throw e;
} }
} }
public async $searchNodeByPublicKeyOrAlias(search: string) {
try {
const searchStripped = search.replace('%', '') + '%';
const query = `SELECT public_key, alias, color FROM nodes WHERE public_key LIKE ? OR alias LIKE ? LIMIT 10`;
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;
}
}
} }
export default new NodesApi(); export default new NodesApi();

View File

@ -7,12 +7,22 @@ class NodesRoutes {
public initRoutes(app: Express) { public initRoutes(app: Express) {
app app
.get(config.MEMPOOL.API_URL_PREFIX + 'statistics/latest', this.$getGeneralStats) .get(config.MEMPOOL.API_URL_PREFIX + 'statistics/latest', this.$getGeneralStats)
.get(config.MEMPOOL.API_URL_PREFIX + 'nodes/search/:search', this.$searchNode)
.get(config.MEMPOOL.API_URL_PREFIX + 'nodes/top', this.$getTopNodes) .get(config.MEMPOOL.API_URL_PREFIX + 'nodes/top', this.$getTopNodes)
.get(config.MEMPOOL.API_URL_PREFIX + 'nodes/:public_key/statistics', this.$getHistoricalNodeStats) .get(config.MEMPOOL.API_URL_PREFIX + 'nodes/:public_key/statistics', this.$getHistoricalNodeStats)
.get(config.MEMPOOL.API_URL_PREFIX + 'nodes/:public_key', this.$getNode) .get(config.MEMPOOL.API_URL_PREFIX + 'nodes/:public_key', this.$getNode)
; ;
} }
private async $searchNode(req: Request, res: Response) {
try {
const nodes = await nodesApi.$searchNodeByPublicKeyOrAlias(req.params.search);
res.json(nodes);
} catch (e) {
res.status(500).send(e instanceof Error ? e.message : e);
}
}
private async $getNode(req: Request, res: Response) { private async $getNode(req: Request, res: Response) {
try { try {
const node = await nodesApi.$getNode(req.params.public_key); const node = await nodesApi.$getNode(req.params.public_key);

View File

@ -3,6 +3,7 @@ import * as express from 'express';
import * as http from 'http'; import * as http from 'http';
import logger from './logger'; import logger from './logger';
import config from './config'; import config from './config';
import generalRoutes from './api/explorer/general.routes';
import nodesRoutes from './api/explorer/nodes.routes'; import nodesRoutes from './api/explorer/nodes.routes';
import channelsRoutes from './api/explorer/channels.routes'; import channelsRoutes from './api/explorer/channels.routes';
@ -30,6 +31,7 @@ class Server {
} }
private initRoutes() { private initRoutes() {
generalRoutes.initRoutes(this.app);
nodesRoutes.initRoutes(this.app); nodesRoutes.initRoutes(this.app);
channelsRoutes.initRoutes(this.app); channelsRoutes.initRoutes(this.app);
} }