polkadot-js / apps

Basic Polkadot/Substrate UI for interacting with a Polkadot and Substrate node. This is the main user-facing application, allowing access to all features available on Substrate chains.
https://dotapps.io
Apache License 2.0
1.74k stars 1.53k forks source link

Add response time to https://polkadot.js.org/apps/ when selecting RPC Nodes #7770

Open ccris02 opened 2 years ago

ccris02 commented 2 years ago

In https://www.dotreasury.com/ksm you can select the node with the lowest response time for optimal performance

image

Would it be possible to add something like that to https://polkadot.js.org/apps/

image

jacogr commented 2 years ago

I did mark it as an enhancement since it is fully and properly specified. However, this is unlikely to get done unless a PR does float in that adds this functionality. (Not sure what this entails coding-wise)

jacogr commented 1 year ago

While I stumbled across this one, here is something I put down a while back (Node script) that actually gets per-endpoint stats. (endpoint + api initial connection time + api health time)

import { ApiPromise, WsProvider } from '@polkadot/api';

const urls = {
    'Dotters Net': 'wss://rpc.dotters.network/polkadot',
    Dwellir: 'wss://polkadot-rpc.dwellir.com',
    'Dwellir Tunisia': 'wss://polkadot-rpc-tn.dwellir.com',
    'IBP Network': 'wss://rpc.ibp.network/polkadot',
    OnFinality: 'wss://polkadot.api.onfinality.io/public-ws',
    Parity: 'wss://rpc.polkadot.io',
    RadiumBlock: 'wss://polkadot.public.curie.radiumblock.co/ws'
};

async function test () {
    const results = await Promise.all(
        Object.keys(urls).map((key) =>
            new Promise((resolve) => {
                const startAt = Date.now();

                ApiPromise
                    .create({
                        provider: new WsProvider(urls[key]),
                        throwOnConnect: true
                    })
                    .then((api) => {
                        const connAt = Date.now();
                        const connTime = connAt - startAt;

                        return api.rpc.system
                            .health()
                            .then(() => [key, connTime, Date.now() - connAt])
                            .catch(() => [key, connTime, -1])
                            .then((r) => {
                                api.disconnect().catch(console.error);
                                resolve(r);
                            });
                    })
                    .catch(() => resolve([key, -1, -1]));
            })
        )
    );

    console.log();

    results.forEach(([key, connTime, healthTime]) =>
        console.log(`${key}`.padStart(20), `${connTime}`.padStart(10), `${healthTime}`.padStart(10))
    );

    setTimeout(test, 5000);
}

test().catch(() => process.exit(-1));

I'm still on the fence on this (and it is most-probably due to me thinking about the approach listed above), since I have to just make random/unused connections to endpoints. What is nice about it through is that it would not allow selection on unavailable endpoints, which is always an issues.

Anyway, if PRs do come in (and especially those with a better approach than mine), really happy to take a look.