Skip to content

Commit

Permalink
Merge pull request #600 from Adamant-im/feat/coin-node-version
Browse files Browse the repository at this point in the history
feat: Show coin node version where available
  • Loading branch information
bludnic authored Mar 4, 2024
2 parents baad2c1 + 8e7a692 commit 88869f0
Show file tree
Hide file tree
Showing 11 changed files with 165 additions and 96 deletions.
4 changes: 2 additions & 2 deletions src/components/nodes/components/NodeVersion.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div v-if="version" :class="classes.version">
{{ 'v' + version }}
{{ version }}
</div>
</template>

Expand All @@ -21,7 +21,7 @@ export default defineComponent({
}
},
setup(props) {
const version = computed(() => props.node.version)
const version = computed(() => props.node.displayVersion)
return {
version,
Expand Down
22 changes: 21 additions & 1 deletion src/lib/nodes/abstract.node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export abstract class Node<C = unknown> {

timer?: NodeJS.Timeout
healthCheckInterval: HealthcheckInterval = 'normal'
abstract client: C
client: C

constructor(
url: string,
Expand All @@ -119,6 +119,14 @@ export abstract class Node<C = unknown> {
this.version = version
this.hasSupportedProtocol = !(this.protocol === 'http:' && appProtocol === 'https:')
this.active = nodesStorage.isActive(url)

this.client = this.buildClient()

if (this.active) {
void this.fetchNodeVersion()
}

void this.startHealthcheck()
}

async startHealthcheck() {
Expand Down Expand Up @@ -176,6 +184,7 @@ export abstract class Node<C = unknown> {
active: this.active,
outOfSync: this.outOfSync,
hasMinNodeVersion: this.hasMinNodeVersion(),
displayVersion: this.displayVersion(),
hasSupportedProtocol: this.hasSupportedProtocol,
socketSupport: this.socketSupport,
height: this.height,
Expand Down Expand Up @@ -209,6 +218,7 @@ export abstract class Node<C = unknown> {
}

protected abstract checkHealth(): Promise<HealthcheckResult>
protected abstract buildClient(): C

/**
* Enables/disables a node.
Expand All @@ -220,6 +230,16 @@ export abstract class Node<C = unknown> {

return this.getStatus()
}

displayVersion() {
return this.version ? `v${this.version}` : ''
}

// This method is not abstract because Not all nodes need version checking (For example: indexers) or some nodes receive version information from healthcheck requests.
// Therefore, it is overridden only in the case when a separate request is needed to obtain the version.
protected fetchNodeVersion() {
return Promise.resolve()
}
}

export type NodeStatusResult = ReturnType<Node['getStatus']>
43 changes: 20 additions & 23 deletions src/lib/nodes/adm/AdmNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,19 @@ export type RequestConfig<P extends Payload> = {
* Encapsulates a node. Provides methods to send API-requests
* to the node and verify is status (online/offline, version, ping, etc.)
*/
export class AdmNode extends Node {
client: AxiosInstance

export class AdmNode extends Node<AxiosInstance> {
constructor(url: string, minNodeVersion = '0.0.0') {
super(url, 'adm', 'node', NODE_LABELS.AdmNode, minNodeVersion, minNodeVersion)
super(url, 'adm', 'node', NODE_LABELS.AdmNode, '', minNodeVersion)

this.wsPort = '36668' // default wsPort
this.wsProtocol = this.protocol === 'https:' ? 'wss:' : 'ws:'
this.wsPortNeeded = this.wsProtocol === 'ws:' && !this.hostname.includes('.onion')
}

this.client = axios.create({
protected buildClient(): AxiosInstance {
return axios.create({
baseURL: this.url
})

// Don't fetch node info if user disabled it
if (this.active) {
void this.fetchNodeInfo()
}
void this.startHealthcheck()
}

/**
Expand Down Expand Up @@ -91,21 +85,24 @@ export class AdmNode extends Node {
* @returns {Promise<{version: string, height: number, ping: number}>}
*/
private async fetchNodeInfo(): Promise<FetchNodeInfoResult> {
const response: GetNodeStatusResponseDto = await this.request({ url: '/api/node/status' })

if (response.success) {
const version = response.version.version
const height = Number(response.network.height)
const socketSupport = response.wsClient ? response.wsClient.enabled : false
const wsPort = response.wsClient ? String(response.wsClient.port) : ''

this.version = version
const { success, version, network, wsClient } = await this.request<
Payload,
GetNodeStatusResponseDto
>({ url: '/api/node/status' })

if (success) {
const readableVersion = version.version
const height = Number(network.height)
const socketSupport = wsClient ? wsClient.enabled : false
const wsPort = wsClient ? String(wsClient.port) : ''

this.version = readableVersion
this.height = height
this.socketSupport = socketSupport
this.wsPort = wsPort

return {
version,
version: readableVersion,
height,
socketSupport,
wsPort
Expand All @@ -117,10 +114,10 @@ export class AdmNode extends Node {

protected async checkHealth() {
const time = Date.now()
const nodeInfo = await this.fetchNodeInfo()
const { height } = await this.fetchNodeInfo()

return {
height: nodeInfo.height,
height,
ping: Date.now() - time
}
}
Expand Down
31 changes: 25 additions & 6 deletions src/lib/nodes/btc/BtcNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,26 @@ import { createBtcLikeClient } from '../utils/createBtcLikeClient'
import type { AxiosInstance } from 'axios'
import { Node } from '@/lib/nodes/abstract.node'
import { NODE_LABELS } from '@/lib/nodes/constants'
import { formatBtcVersion } from '@/lib/nodes/utils/nodeVersionFormatters.ts'

type FetchBtcNodeInfoResult = {
error: string
result: {
version: number
}
}

/**
* Encapsulates a node. Provides methods to send API-requests
* to the node and verify is status (online/offline, version, ping, etc.)
*/
export class BtcNode extends Node {
client: AxiosInstance

export class BtcNode extends Node<AxiosInstance> {
constructor(url: string) {
super(url, 'btc', 'node', NODE_LABELS.BtcNode)
}

this.client = createBtcLikeClient(url)

void this.startHealthcheck()
protected buildClient(): AxiosInstance {
return createBtcLikeClient(this.url)
}

protected async checkHealth() {
Expand All @@ -29,4 +35,17 @@ export class BtcNode extends Node {
ping: Date.now() - time
}
}

protected async fetchNodeVersion(): Promise<void> {
const { data } = await this.client.post<FetchBtcNodeInfoResult>('/bitcoind', {
jsonrpc: '1.0',
id: 'adm',
method: 'getnetworkinfo',
params: []
})
const { version } = data.result
if (version) {
this.version = formatBtcVersion(version)
}
}
}
27 changes: 21 additions & 6 deletions src/lib/nodes/dash/DashNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ import type { AxiosInstance } from 'axios'
import { Node } from '@/lib/nodes/abstract.node'
import { NODE_LABELS } from '@/lib/nodes/constants'

type FetchNodeVersionResponse = {
error: string
result: {
buildversion: string
}
}

/**
* Encapsulates a node. Provides methods to send API-requests
* to the node and verify is status (online/offline, version, ping, etc.)
*/
export class DashNode extends Node {
client: AxiosInstance

export class DashNode extends Node<AxiosInstance> {
constructor(url: string) {
super(url, 'dash', 'node', NODE_LABELS.DashNode)
}

this.client = createBtcLikeClient(url)

void this.startHealthcheck()
protected buildClient(): AxiosInstance {
return createBtcLikeClient(this.url)
}

protected async checkHealth() {
Expand All @@ -31,4 +36,14 @@ export class DashNode extends Node {
ping: Date.now() - time
}
}

protected async fetchNodeVersion(): Promise<void> {
const { data } = await this.client.post<FetchNodeVersionResponse>('/', {
method: 'getnetworkinfo'
})
const { buildversion } = data.result
if (buildversion) {
this.version = buildversion.replace('v', '')
}
}
}
25 changes: 19 additions & 6 deletions src/lib/nodes/doge/DogeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@ import { createBtcLikeClient } from '../utils/createBtcLikeClient'
import type { AxiosInstance } from 'axios'
import { Node } from '@/lib/nodes/abstract.node'
import { NODE_LABELS } from '@/lib/nodes/constants'
import { formatDogeVersion } from '@/lib/nodes/utils/nodeVersionFormatters.ts'

type FetchBtcNodeInfoResult = {
info: {
version: number
}
}

/**
* Encapsulates a node. Provides methods to send API-requests
* to the node and verify is status (online/offline, version, ping, etc.)
*/
export class DogeNode extends Node {
client: AxiosInstance

export class DogeNode extends Node<AxiosInstance> {
constructor(url: string) {
super(url, 'doge', 'node', NODE_LABELS.DogeNode)
}

this.client = createBtcLikeClient(url)

void this.startHealthcheck()
protected buildClient(): AxiosInstance {
return createBtcLikeClient(this.url)
}

protected async checkHealth() {
Expand All @@ -29,4 +34,12 @@ export class DogeNode extends Node {
ping: Date.now() - time
}
}

protected async fetchNodeVersion(): Promise<void> {
const { data } = await this.client.get<FetchBtcNodeInfoResult>('/api/status')
const { version } = data.info
if (version) {
this.version = formatDogeVersion(version)
}
}
}
14 changes: 4 additions & 10 deletions src/lib/nodes/eth-indexer/EthIndexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,13 @@ import { NODE_LABELS } from '@/lib/nodes/constants'
* ETH Indexer API
* https://github.com/Adamant-im/ETH-transactions-storage
*/
export class EthIndexer extends Node {
client: AxiosInstance

export class EthIndexer extends Node<AxiosInstance> {
constructor(url: string) {
super(url, 'eth', 'service', NODE_LABELS.EthIndexer)
}

this.client = axios.create({ baseURL: url })

// Don't fetch node info if user disabled it
if (this.active) {
void this.fetchServiceInfo()
}
void this.startHealthcheck()
protected buildClient(): AxiosInstance {
return axios.create({ baseURL: this.url })
}

/**
Expand Down
26 changes: 16 additions & 10 deletions src/lib/nodes/eth/EthNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,21 @@ import Web3Eth from 'web3-eth'
import { HttpProvider } from 'web3-providers-http'
import { Node } from '@/lib/nodes/abstract.node'
import { NODE_LABELS } from '@/lib/nodes/constants'
import { formatEthVersion } from '@/lib/nodes/utils/nodeVersionFormatters.ts'

/**
* Encapsulates a node. Provides methods to send API-requests
* to the node and verify is status (online/offline, version, ping, etc.)
*/
export class EthNode extends Node {
/**
* @custom
*/
provider: HttpProvider
client: Web3Eth
export class EthNode extends Node<Web3Eth> {
clientName = ''

constructor(url: string) {
super(url, 'eth', 'node', NODE_LABELS.EthNode)
}

this.provider = new HttpProvider(this.url)
this.client = new Web3Eth(this.provider)

void this.startHealthcheck()
protected buildClient(): Web3Eth {
return new Web3Eth(new HttpProvider(this.url))
}

protected async checkHealth() {
Expand All @@ -32,4 +28,14 @@ export class EthNode extends Node {
ping: Date.now() - time
}
}

protected async fetchNodeVersion(): Promise<void> {
const { clientName, simplifiedVersion } = formatEthVersion(await this.client.getNodeInfo())
this.version = simplifiedVersion
this.clientName = clientName
}

displayVersion(): string {
return this.clientName && this.version ? `${this.clientName}/${this.version}` : ''
}
}
14 changes: 4 additions & 10 deletions src/lib/nodes/lsk-indexer/LskIndexer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,13 @@ import { Endpoints } from './types/api/endpoints'
* Encapsulates a node. Provides methods to send API-requests
* to the node and verify is status (online/offline, version, ping, etc.)
*/
export class LskIndexer extends Node {
client: AxiosInstance

export class LskIndexer extends Node<AxiosInstance> {
constructor(url: string) {
super(url, 'lsk', 'service', NODE_LABELS.LskIndexer)
}

this.client = axios.create({ baseURL: `${url}/api/v3` })

// Don't fetch node info if user disabled it
if (this.active) {
void this.fetchServiceInfo()
}
void this.startHealthcheck()
protected buildClient(): AxiosInstance {
return axios.create({ baseURL: `${this.url}/api/v3` })
}

/**
Expand Down
Loading

0 comments on commit 88869f0

Please sign in to comment.