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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ yarn start
+ `/block/NUMBER` fetch block details at block height `NUMBER`.
+ `/balance/ADDRESS` fetch balances for `ADDRESS` at latest finalized block.
+ `/balance/ADDRESS/NUMBER` fetch balances for `ADDRESS` at block height `NUMBER`.
+ `/metadata` fetch chain metadata at latest finalized block.
+ `/metadata/NUMBER` fetch chain metadata at block height `NUMBER`.

### Configuration

Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "polkadot-rpc-proxy",
"version": "0.1.6",
"version": "0.1.7",
"description": "",
"main": "index.js",
"scripts": {
Expand All @@ -11,10 +11,10 @@
"author": "",
"license": "GPL-3.0-or-later",
"dependencies": {
"@polkadot/api": "1.4.0-beta.45",
"@polkadot/metadata": "1.4.0-beta.45",
"@polkadot/rpc-provider": "1.4.0-beta.45",
"@polkadot/types": "1.4.0-beta.45",
"@polkadot/api": "1.5.1",
"@polkadot/metadata": "1.5.1",
"@polkadot/rpc-provider": "1.5.1",
"@polkadot/types": "1.5.1",
"@types/express": "^4.17.2",
"express": "^4.17.1",
"typescript": "^3.8.2"
Expand Down
28 changes: 17 additions & 11 deletions src/ApiHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,10 @@ export default class ApiHandler {
}

async fetchBlock(hash: BlockHash) {
await this.ensureMeta(hash);

const { api } = this;
const api = await this.ensureMeta(hash);
const [{ block }, events] = await Promise.all([
api.rpc.chain.getBlock(hash),
this.fetchEvents(hash),
this.fetchEvents(api, hash),
]);

const { parentHash, number, stateRoot, extrinsicsRoot } = block.header;
Expand Down Expand Up @@ -126,9 +124,7 @@ export default class ApiHandler {
}

async fetchBalance(hash: BlockHash, address: string) {
await this.ensureMeta(hash);

const { api } = this;
const api = await this.ensureMeta(hash);

const [header, free, reserved, locks, nonce] = await Promise.all([
api.rpc.chain.getHeader(hash),
Expand All @@ -146,15 +142,23 @@ export default class ApiHandler {
return { at, nonce, free, reserved, locks };
}

async fetchEvents(hash: BlockHash): Promise<EventRecord[] | string> {
async fetchMetadata(hash: BlockHash) {
const api = await this.ensureMeta(hash);

const metadata = await api.rpc.state.getMetadata(hash);

return metadata;
}

async fetchEvents(api: ApiPromise, hash: BlockHash): Promise<EventRecord[] | string> {
try {
return await await this.api.query.system.events.at(hash);
return await await api.query.system.events.at(hash);
} catch (_) {
return 'Unable to fetch Events, cannot confirm extrinsic status. Check pruning settings on the node.';
}
}

async ensureMeta(hash: BlockHash) {
async ensureMeta(hash: BlockHash): Promise<ApiPromise> {
const { api } = this;

try {
Expand All @@ -167,13 +171,15 @@ export default class ApiHandler {
const meta = await api.rpc.state.getMetadata(hash);
const chain = await api.rpc.system.chain();

api.registry.register(getSpecTypes(chain, runtimeVersion));
api.registry.register(getSpecTypes(api.registry, chain, runtimeVersion));
api.registry.setMetadata(meta);
}
} catch (err) {
console.error(`Failed to get Metadata for block ${hash}, using latest.`);
console.error(err);
this.specVersion = api.createType('u32', -1);
}

return api;
}
}
46 changes: 44 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ const WS_URL = process.env.NODE_WS_URL || 'ws://127.0.0.1:9944';

type Params = { [key: string]: string };

interface Error {
error: string;
}

function parseNumber(n: string): [Error | null, number] {
const num = Number(n);

if (!Number.isInteger(num)) {
return [{ error: 'Invalid block number' }, 0];
}

return [null, num];
}

async function main() {
const api = await ApiPromise.create({ provider: new WsProvider(WS_URL) });
const handler = new ApiHandler(api);
Expand All @@ -47,7 +61,12 @@ async function main() {
get('/', async (req) => 'Sidecar is running, go to /block to get latest finalized block');

get('/block/:number', async (params) => {
const number = Number(params.number) || 0;
const [error, number] = parseNumber(params.number);

if (error) {
return error;
}

const hash = await api.rpc.chain.getBlockHash(number);

return await handler.fetchBlock(hash);
Expand All @@ -68,12 +87,35 @@ async function main() {

get('/balance/:address/:number', async (params) => {
const { address } = params;
const number = Number(params.number) || 0;
const [error, number] = parseNumber(params.number);

if (error) {
return error;
}

const hash = await api.rpc.chain.getBlockHash(number);

return await handler.fetchBalance(hash, address);
});

get('/metadata/', async () => {
const hash = await api.rpc.chain.getFinalizedHead();

return await handler.fetchMetadata(hash);
});

get('/metadata/:number', async (params) => {
const [error, number] = parseNumber(params.number);

if (error) {
return error;
}

const hash = await api.rpc.chain.getBlockHash(number);

return await handler.fetchMetadata(hash);
});

app.listen(PORT, HOST, () => console.log(`Running on http://${HOST}:${PORT}/`))
}

Expand Down
Loading