Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ a 32-byte hex string (`0x` followed by 64 hexadecimal digits) that denotes the b

- [`/metadata/NUMBER` fetch chain metadata at the block identified by 'NUMBER`.](src/controllers/runtime/RuntimeMetadataController.ts)

- [`node/network` fetch information about the Substrate node's activity in the peer-to-peer network.](src/controllers/node/NodeNetworkController.ts)

- [`node/transaction-pool` fetch pending extrinsics from the Substrate node.](src/controllers/node/NodeTransactionPoolController.ts)

- [`/node/version` fetch information about the Substrates node's implementation and versioning.](src/controllers/node/NodeVersionController.ts)

- [`/claims/ADDRESS` fetch claims data for an Ethereum `ADDRESS`.](src/controllers/claims/ClaimsController.ts)

- [`/claims/ADDRESS/NUMBER` fetch claims data for an Ethereum `ADDRESS` at the block identified by 'NUMBER`.](src/controllers/claims/ClaimsController.ts)
Expand Down
41 changes: 22 additions & 19 deletions openapi/openapi-proposal.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ paths:
get:
tags:
- node
summary: Get network information of the node.
summary: Get information about the Substrate node's activity in the peer-to-peer network.
description: Returns network related information of the node.
operationId: getNodeNetworking
responses:
Expand All @@ -286,7 +286,7 @@ paths:
get:
tags:
- node
summary: Get the transaction pool of the node.
summary: Get pending extrinsics from the Substrate node.
description: Returns the extrinsics that the node knows of that have not
been included in a block.
operationId: getNodeTransactionPool
Expand All @@ -301,7 +301,7 @@ paths:
get:
tags:
- node
summary: Get version information of the node.
summary: Get information about the Substrates node's implementation and versioning.
description: Returns versioning information of the node.
operationId: getNodeVersion
responses:
Expand Down Expand Up @@ -1507,17 +1507,15 @@ components:
NodeVersion:
type: object
properties:
at:
$ref: '#/components/schemas/BlockIdentifiers'
clientImplVersion:
clientVersion:
type: string
description: Node's implementation's version.
description: Node's binary version.
clientImplName:
type: string
description: Node's implementation name.
chain:
type: string
description: Chain's spec name.
description: Node's chain name.
description: Version information of the node.
NodeRole:
type: string
Expand All @@ -1535,27 +1533,25 @@ components:
description: Peer ID.
roles:
type: string
description: Roles.
description: Roles the peer is running
protocolVersion:
type: string
description: Protocol version.
description: Peer's protocol version.
format: unsignedInteger
bestHash:
type: string
description: Peer best block hash.
description: Hash of the best block on the peer's canon chain.
format: hex
bestNumber:
type: string
description: Peer
description: Height of the best block on the peer's canon chain.
format: unsignedInteger
NodeNetwork:
type: object
properties:
at:
$ref: '#/components/schemas/BlockIdentifiers'
nodeRoles:
$ref: '#/components/schemas/NodeRole'
peers:
numPeers:
type: string
description: Number of peers the node is connected to.
format: unsignedInteger
Expand All @@ -1577,7 +1573,7 @@ components:
example.
items:
type: string
systemPeers:
peersInfo:
type: array
items:
$ref: '#/components/schemas/PeerInfo'
Expand Down Expand Up @@ -1841,12 +1837,19 @@ components:
TransactionPool:
type: object
properties:
at:
$ref: '#/components/schemas/BlockIdentifiers'
pool:
type: array
items:
$ref: '#/components/schemas/Extrinsic'
type: object
properties:
hash:
type: string
format: hex
description: H256 hash of the extrinsic.
encodedExtrinsic:
type: string
format: hex
description: Scale encoded extrinsic.
PalletsResponses:
oneOf:
- type: object
Expand Down
1 change: 1 addition & 0 deletions src/controllers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './blocks';
export * from './claims';
export * from './runtime';
export * from './pallets';
export * from './node';
59 changes: 59 additions & 0 deletions src/controllers/node/NodeNetworkController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { ApiPromise } from '@polkadot/api';
import { RequestHandler } from 'express';

import { NodeNetworkService } from '../../services';
import AbstractController from '../AbstractController';

/**
* GET information about the Substrate node's activity in the peer-to-peer network.
*
* Returns:
* - `nodeRoles`: Roles the node is running.
* - `numPeers`: Number of peers the node is connected to.
* - `isSyncing`: Whether or not the node is syncing. `False` indicates that the
* node is in sync.
* - `shouldHavePeers`: Whether or not the node should be connected to peers. Might
* be false for local chains or when running without discovery.
* - `localPeerId`: Local copy of the `PeerId`.
* - `localListenAddresses`: Multiaddresses that the local node is listening on.
* The addresses include a trailing `/p2p/` with the local PeerId, and are thus
* suitable to be passed to `system_addReservedPeer` or as a bootnode address
* for example.
* - `systemPeers`: array of
* - `peerId`: Peer ID.
* - `roles`: Roles the peer is running.
* - `protocolVersion`: Peer's protocol version.
* - `bestHash`: Hash of the best block on the peers canon chain.
* - `bestNumber`: Height of the best block on the peers canon chain.
*
* References:
* - `NodeRole`: https://github.com/paritytech/substrate/blob/master/client/rpc-api/src/system/helpers.rs#L80
*/
export default class NodeNetworkController extends AbstractController<
NodeNetworkService
> {
constructor(api: ApiPromise) {
super(api, '/node/network', new NodeNetworkService(api));
this.initRoutes();
}

protected initRoutes(): void {
this.safeMountAsyncGetHandlers([['', this.getNodeNetworking]]);
}

/**
* GET information about the Substrate node's activity in the peer-to-peer network.
*
* @param _req Express Request
* @param res Express Response
*/
private getNodeNetworking: RequestHandler = async (
_req,
res
): Promise<void> => {
NodeNetworkController.sanitizedSend(
res,
await this.service.fetchNetwork()
);
};
}
48 changes: 48 additions & 0 deletions src/controllers/node/NodeTransactionPoolController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { ApiPromise } from '@polkadot/api';
import { RequestHandler } from 'express';

import { NodeTransactionPoolService } from '../../services';
import AbstractController from '../AbstractController';

/**
* GET pending extrinsics from the Substrate node.
*
* Returns:
* - `pool`: array of
* - `hash`: H256 hash of the extrinsic.
* - `encodedExtrinsic`: Scale encoded extrinsic.
*/
export default class NodeTransactionPoolController extends AbstractController<
NodeTransactionPoolService
> {
constructor(api: ApiPromise) {
super(
api,
'/node/transaction-pool',
new NodeTransactionPoolService(api)
);
this.initRoutes();
}

protected initRoutes(): void {
this.safeMountAsyncGetHandlers([['', this.getNodeTransactionPool]]);
}

/**
** GET pending extrinsics from the Substrate node.
*
* @param _req Express Request
* @param res Express Response
*/
private getNodeTransactionPool: RequestHandler = async (
_req,
res
): Promise<void> => {
const hash = await this.api.rpc.chain.getFinalizedHead();

NodeTransactionPoolController.sanitizedSend(
res,
await this.service.fetchTransactionPool(hash)
);
};
}
39 changes: 39 additions & 0 deletions src/controllers/node/NodeVersionController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { ApiPromise } from '@polkadot/api';
import { RequestHandler } from 'express';

import { NodeVersionService } from '../../services';
import AbstractController from '../AbstractController';

/**
* GET information about the Substrates node's implementation and versioning.
*
* Returns:
* - `clientVersion`: Node binary version.
* - `clientImplName`: Node's implementation name.
* - `chain`: Node's chain name.
*/
export default class NodeVersionController extends AbstractController<
NodeVersionService
> {
constructor(api: ApiPromise) {
super(api, '/node/version', new NodeVersionService(api));
this.initRoutes();
}

protected initRoutes(): void {
this.safeMountAsyncGetHandlers([['', this.getNodeVersion]]);
}

/**
* GET information about the Substrates node's implementation and versioning.
*
* @param _req Express Request
* @param res Express Response
*/
getNodeVersion: RequestHandler = async (_req, res): Promise<void> => {
NodeVersionController.sanitizedSend(
res,
await this.service.fetchVersion()
);
};
}
3 changes: 3 additions & 0 deletions src/controllers/node/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export { default as NodeNetwork } from './NodeNetworkController';
export { default as NodeVersion } from './NodeVersionController';
export { default as NodeTransactionPool } from './NodeTransactionPoolController';
8 changes: 8 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ async function main() {
const stakingController = new controllers.PalletsStakingProgress(api);
const vestingController = new controllers.AccountsVestingInfo(api);
const metadataController = new controllers.Metadata(api);
const nodeNetworkController = new controllers.NodeNetwork(api);
const nodeVersionController = new controllers.NodeVersion(api);
const nodeTransactionPoolController = new controllers.NodeTransactionPool(
api
);
const claimsController = new controllers.Claims(api);
const txArtifactsController = new controllers.TransactionMaterial(api);
const txFeeEstimateController = new controllers.TransactionFeeEstimate(api);
Expand All @@ -81,6 +86,9 @@ async function main() {
stakingController,
vestingController,
metadataController,
nodeNetworkController,
nodeVersionController,
nodeTransactionPoolController,
claimsController,
txArtifactsController,
txFeeEstimateController,
Expand Down
1 change: 1 addition & 0 deletions src/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ export * from './pallets';
export * from './transaction';
export * from './claims';
export * from './runtime';
export * from './node';
16 changes: 16 additions & 0 deletions src/services/node/NodeNetworkService.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { sanitizeNumbers } from '../../sanitize/sanitizeNumbers';
import { mockApi } from '../test-helpers/mock';
import * as nodeNetworkResponse from '../test-helpers/responses/node/network.json';
import { NodeNetworkService } from '.';

const nodeNetworkService = new NodeNetworkService(mockApi);

describe('NodeNetworkService', () => {
describe('fetchNetwork', () => {
it('works when ApiPromise works', async () => {
expect(
sanitizeNumbers(await nodeNetworkService.fetchNetwork())
).toStrictEqual(nodeNetworkResponse);
});
});
});
36 changes: 36 additions & 0 deletions src/services/node/NodeNetworkService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { INodeNetwork } from 'src/types/responses';

import { AbstractService } from '../AbstractService';

export class NodeNetworkService extends AbstractService {
async fetchNetwork(): Promise<INodeNetwork> {
const [
{ peers: numPeers, isSyncing, shouldHavePeers },
localPeerId,
nodeRoles,
localListenAddresses,
] = await Promise.all([
this.api.rpc.system.health(),
this.api.rpc.system.localPeerId(),
this.api.rpc.system.nodeRoles(),
this.api.rpc.system.localListenAddresses(),
]);

let peersInfo;
try {
peersInfo = await this.api.rpc.system.peers();
} catch {
peersInfo = 'Cannot query system_peers from node.';
}

return {
nodeRoles,
numPeers,
isSyncing,
shouldHavePeers,
localPeerId,
localListenAddresses,
peersInfo,
};
}
}
Loading