Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1649792
commit 8c58a22
Showing
9 changed files
with
878 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
root = true | ||
|
||
[*] | ||
end_of_line = lf | ||
trim_trailing_whitespace = true | ||
insert_final_newline = true | ||
charset = utf-8 | ||
|
||
[*.{js,ts}] | ||
indent_style = space | ||
indent_size = 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
node_modules/ | ||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
{ | ||
printWidth: 100, | ||
trailingComma: "all" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
## License & History | ||
|
||
MIT. | ||
|
||
Classes created until October 2018 are taken from the MIT-licensed | ||
lisk-argus by Hendrik Hofstadt & Lisk Builders. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "libargus", | ||
"version": "0.1.0", | ||
"description": "A typesafe MIT licensed library to interact with the Lisk blockchain", | ||
"main": "build/index.js", | ||
"repository": "https://github.com/prolina-foundation/libargus", | ||
"author": "Simon Warta & Lisk Builders", | ||
"license": "MIT", | ||
"scripts": { | ||
"format": "prettier --write './src/**/*.ts'", | ||
"prebuild": "yarn format", | ||
"build": "tsc", | ||
"test": "mocha \"build/**/*.spec.js\"" | ||
}, | ||
"dependencies": { | ||
"request": "^2.88.0", | ||
"request-promise-native": "^1.0.5" | ||
}, | ||
"devDependencies": { | ||
"@types/chai": "^4.1.7", | ||
"@types/mocha": "^5.2.5", | ||
"@types/request": "^2.48.0", | ||
"@types/request-promise-native": "^1.0.15", | ||
"chai": "^4.2.0", | ||
"mocha": "^5.2.0", | ||
"prettier": "^1.14.3", | ||
"typescript": "^3.1.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
import { expect } from "chai"; | ||
|
||
import { HttpApi } from "./HttpApi"; | ||
|
||
const nodeHostname = process.env.LISK_NODE_HOSTNAME || "testnet.lisk.io"; | ||
const nodePort = Number.parseInt(process.env.LISK_NODE_PORT || "7000", 10); | ||
const nodeSecure = !!process.env.LISK_NODE_SECURE; | ||
|
||
describe("HttpApi", () => { | ||
let api: HttpApi; | ||
|
||
beforeEach(() => { | ||
api = new HttpApi(nodeHostname, nodePort, nodeSecure); | ||
}); | ||
|
||
it("can get node status", async () => { | ||
const status = await api.getNodeStatus(); | ||
expect(status.data.broadhash).to.match(/^[0-9a-f]{64}$/); | ||
expect(status.data.consensus).to.be.gt(0); | ||
expect(status.data.consensus).to.be.lte(100); | ||
expect(status.data.height).to.be.gt(1); | ||
expect(status.data.height).to.be.lt(10_000_000); | ||
expect(status.data.networkHeight).to.be.gt(1); | ||
expect(status.data.networkHeight).to.be.lt(10_000_000); | ||
expect(status.data.loaded).to.be.true; | ||
expect(status.data.syncing).to.be.false; | ||
expect(status.data.transactions).to.be.not.undefined; | ||
}); | ||
|
||
it("can get blocks", async () => { | ||
const response = await api.getBlocks(); | ||
expect(response.data.length).to.equal(100); | ||
for (const block of response.data) { | ||
expect(block.id).to.match(/^[0-9]+$/); | ||
expect(block.height).to.be.within(1, 10_000_000); | ||
expect(block.generatorPublicKey).to.match(/^[0-9a-f]{64}$/); | ||
} | ||
}); | ||
|
||
it("can get forgers", async () => { | ||
const response = await api.getForgers(); | ||
expect(response.data.length).to.equal(100); | ||
for (const forger of response.data) { | ||
expect(forger.username).to.match(/^[a-zA-Z0-9_\.]+$/); | ||
expect(forger.publicKey).to.match(/^[0-9a-f]{64}$/); | ||
} | ||
}); | ||
|
||
it("can get delegates", async () => { | ||
const response = await api.getDelegates(); | ||
expect(response.data.length).to.equal(101); | ||
for (const delegate of response.data) { | ||
expect(delegate.rank).to.be.within(1, 101); | ||
expect(delegate.username).to.match(/^[a-zA-Z0-9_\.]+$/); | ||
expect(delegate.producedBlocks).to.gte(0); | ||
expect(delegate.missedBlocks).to.gte(0); | ||
expect(delegate.productivity).to.be.within(0, 100); | ||
} | ||
}); | ||
|
||
it("can get last block by delegate", async () => { | ||
const response = await api.getDelegates(); | ||
const firstDelegate = response.data[0]; | ||
|
||
const lastBlock = await api.getLastBlockByDelegate(firstDelegate.account.publicKey); | ||
expect(lastBlock.id).to.match(/^[0-9]+$/); | ||
expect(lastBlock.height).to.be.within(1, 10_000_000); | ||
expect(lastBlock.generatorPublicKey).to.eql(firstDelegate.account.publicKey); | ||
}); | ||
|
||
it("can get block by height", async () => { | ||
const block = await api.getBlockByHeight(1); | ||
|
||
expect(block.id).to.match(/^[0-9]+$/); | ||
expect(block.height).to.be.within(1, 10_000_000); | ||
expect(block.generatorPublicKey).to.match(/^[0-9a-f]{64}$/); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import * as request from "request-promise-native"; | ||
|
||
// Lisk HTTP API | ||
// https://app.swaggerhub.com/apis/LiskHQ/Lisk | ||
export class HttpApi { | ||
constructor( | ||
protected readonly hostname: string, | ||
protected readonly port: number, | ||
protected readonly secure: boolean = false, | ||
) {} | ||
|
||
public getNodeStatus(): Promise<ResponseObject<NodeStatusExtended>> { | ||
const options = { json: true }; | ||
return request(`${this.baseUrl()}/node/status`, options).promise(); | ||
} | ||
|
||
public getBlocks(): Promise<ResponseList<Block>> { | ||
const options = { json: true }; | ||
return request(`${this.baseUrl()}/blocks?limit=100`, options).promise(); | ||
} | ||
|
||
public getForgers(): Promise<ForgerResponse> { | ||
const options = { json: true }; | ||
return request(`${this.baseUrl()}/delegates/forgers?limit=100`, options).promise(); | ||
} | ||
|
||
public getDelegates(): Promise<ResponseList<DelegateDetails>> { | ||
const options = { json: true }; | ||
return request(`${this.baseUrl()}/delegates?limit=101&sort=rank:asc`, options).promise(); | ||
} | ||
|
||
public getLastBlockByDelegate(generatorKey: string): Promise<Block> { | ||
const options = { json: true }; | ||
return request(`${this.baseUrl()}/blocks?limit=1&generatorPublicKey=${generatorKey}`, options) | ||
.promise() | ||
.then(data => data.data[0]); | ||
} | ||
|
||
public getBlockByHeight(height: number): Promise<Block> { | ||
const options = { json: true }; | ||
return request(`${this.baseUrl()}/blocks?limit=1&height=${height}`, options) | ||
.promise() | ||
.then(data => data.data[0]); | ||
} | ||
|
||
// method is proteced to allow adding endpoints by subclassing | ||
protected baseUrl(): string { | ||
const protocol = this.secure ? "https" : "http"; | ||
return `${protocol}://${this.hostname}:${this.port}/api`; | ||
} | ||
} | ||
|
||
export interface Block { | ||
readonly id: string; | ||
readonly version: number; | ||
readonly timestamp: number; | ||
readonly height: number; | ||
readonly numberOfTransactions: number; | ||
readonly totalAmount: string; | ||
readonly totalFee: string; | ||
readonly reward: string; | ||
readonly payloadLength: number; | ||
readonly payloadHash: string; | ||
readonly generatorPublicKey: string; | ||
readonly blockSignature: string; | ||
readonly confirmations: number; | ||
readonly totalForged: string; | ||
readonly generatorAddress: string; | ||
readonly previousBlockId: string; | ||
} | ||
|
||
export interface TransactionsStats { | ||
readonly confirmed: number; | ||
readonly unconfirmed: number; | ||
readonly unprocessed: number; | ||
readonly unsigned: number; | ||
readonly total: number; | ||
} | ||
|
||
export interface NodeStatusExtended { | ||
readonly broadhash: string; | ||
readonly consensus: number; | ||
readonly height: number; | ||
readonly loaded: boolean; | ||
readonly networkHeight: number; | ||
readonly syncing: boolean; | ||
readonly transactions: TransactionsStats; | ||
} | ||
|
||
export interface ForgerMeta { | ||
readonly lastBlock: number; | ||
readonly lastBlockSlot: number; | ||
readonly currentSlot: number; | ||
readonly limit: number; | ||
readonly offset: number; | ||
} | ||
|
||
export interface ForgerDetail { | ||
readonly publicKey: string; | ||
readonly username: string; | ||
readonly address: string; | ||
readonly nextSlot: number; | ||
} | ||
|
||
export interface ForgerResponse { | ||
readonly meta: ForgerMeta; | ||
readonly data: ForgerDetail[]; | ||
} | ||
|
||
export interface Account { | ||
readonly address: string; | ||
readonly publicKey: string; | ||
readonly secondPublicKey: string; | ||
} | ||
|
||
export type DelegateDetails = { | ||
readonly rewards: string; | ||
readonly vote: string; | ||
readonly producedBlocks: number; | ||
readonly missedBlocks: number; | ||
readonly username: string; | ||
readonly rank: number; | ||
readonly approval: number; | ||
readonly productivity: number; | ||
readonly account: Account; | ||
}; | ||
|
||
export interface ResponseObject<T> { | ||
readonly meta: any; | ||
readonly data: T; | ||
} | ||
|
||
export interface ResponseList<T> { | ||
readonly meta: any; | ||
readonly data: T[]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"compilerOptions": { | ||
"strict": true, | ||
"target": "es2015", | ||
"module": "commonjs", | ||
"sourceMap": true, | ||
"outDir": "build" | ||
} | ||
} |
Oops, something went wrong.