mirror of
https://github.com/pezkuwichain/pezkuwi-apps.git
synced 2026-04-25 02:17:55 +00:00
feat: initial Pezkuwi Apps rebrand from polkadot-apps
Rebranded terminology: - Polkadot → Pezkuwi - Kusama → Dicle - Westend → Zagros - Rococo → PezkuwiChain - Substrate → Bizinikiwi - parachain → teyrchain Custom logos with Kurdistan brand colors (#e6007a → #86e62a): - bizinikiwi-hexagon.svg - sora-bizinikiwi.svg - hezscanner.svg - heztreasury.svg - pezkuwiscan.svg - pezkuwistats.svg - pezkuwiassembly.svg - pezkuwiholic.svg
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
// Copyright 2017-2025 @pezkuwi/apps-config authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
|
||||
|
||||
import { assert, isString } from '@pezkuwi/util';
|
||||
import { WebSocket } from '@pezkuwi/x-ws';
|
||||
|
||||
import { createWsEndpoints } from '../endpoints/index.js';
|
||||
import { fetchJson } from './fetch.js';
|
||||
|
||||
interface Endpoint {
|
||||
name: string;
|
||||
ws: string;
|
||||
}
|
||||
|
||||
interface DnsResponse {
|
||||
Answer?: { name: string }[];
|
||||
Question: { name: string }[];
|
||||
}
|
||||
|
||||
const TIMEOUT = 60_000;
|
||||
|
||||
function noopHandler () {
|
||||
// ignore
|
||||
}
|
||||
|
||||
describe('check endpoints', (): void => {
|
||||
const checks = createWsEndpoints()
|
||||
.filter(({ isDisabled, isUnreachable, value }) =>
|
||||
!isDisabled &&
|
||||
!isUnreachable &&
|
||||
value &&
|
||||
isString(value) &&
|
||||
!value.includes('127.0.0.1') &&
|
||||
!value.startsWith('light://')
|
||||
)
|
||||
.map(({ text, value }): Partial<Endpoint> => ({
|
||||
name: text as string,
|
||||
ws: value
|
||||
}))
|
||||
.filter((v): v is Endpoint => !!v.ws);
|
||||
|
||||
for (const { name, ws: endpoint } of checks) {
|
||||
it(`${name} @ ${endpoint}`, async (): Promise<void> => {
|
||||
const [,, hostWithPort] = endpoint.split('/');
|
||||
const [host] = hostWithPort.split(':');
|
||||
let websocket: WebSocket | null = null;
|
||||
let closeTimerId: ReturnType<typeof setTimeout> | null = null;
|
||||
|
||||
await fetchJson<DnsResponse>(`https://dns.google/resolve?name=${host}`)
|
||||
.then((json) =>
|
||||
assert(json?.Answer, 'No DNS entry')
|
||||
)
|
||||
.then(() =>
|
||||
new Promise((resolve, reject): void => {
|
||||
websocket = new WebSocket(endpoint);
|
||||
|
||||
websocket.onclose = (event: { code: number; reason: string }): void => {
|
||||
if (event.code !== 1000) {
|
||||
reject(new Error(`Disconnected, code: '${event.code}' reason: '${event.reason}'`));
|
||||
}
|
||||
};
|
||||
|
||||
websocket.onerror = (): void => {
|
||||
reject(new Error('Connection error'));
|
||||
};
|
||||
|
||||
websocket.onopen = (): void => {
|
||||
websocket?.send('{"id":"1","jsonrpc":"2.0","method":"state_getMetadata","params":[]}');
|
||||
};
|
||||
|
||||
websocket.onmessage = (message: { data: string }): void => {
|
||||
try {
|
||||
const result = (JSON.parse(message.data) as { result?: string }).result;
|
||||
|
||||
assert(result?.startsWith('0x'), 'Invalid/non-hex response');
|
||||
resolve(result);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
};
|
||||
|
||||
closeTimerId = setTimeout(
|
||||
() => {
|
||||
closeTimerId = null;
|
||||
reject(new Error('Connection timeout'));
|
||||
},
|
||||
TIMEOUT
|
||||
);
|
||||
})
|
||||
)
|
||||
.finally(() => {
|
||||
if (closeTimerId) {
|
||||
clearTimeout(closeTimerId);
|
||||
closeTimerId = null;
|
||||
}
|
||||
|
||||
if (websocket) {
|
||||
websocket.onclose = noopHandler;
|
||||
websocket.onerror = noopHandler;
|
||||
websocket.onopen = noopHandler;
|
||||
websocket.onmessage = noopHandler;
|
||||
|
||||
try {
|
||||
websocket.close();
|
||||
} catch (e) {
|
||||
console.error((e as Error).message);
|
||||
}
|
||||
|
||||
websocket = null;
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2017-2025 @pezkuwi/apps-config authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import { fetch } from '@pezkuwi/x-fetch';
|
||||
|
||||
function fetchWithTimeout (url: string, timeout = 2_000): Promise<Response | null> {
|
||||
let controller: AbortController | null = new AbortController();
|
||||
let timeoutId: null | ReturnType<typeof setTimeout> = null;
|
||||
|
||||
// This is a weird mess, however we seem to have issues with Jest & hanging connections
|
||||
// in the case where things are (possibly) aborted. So we just swallow/log everything
|
||||
// and return null in the cases where things don't quite go as planned
|
||||
return Promise
|
||||
.race([
|
||||
fetch(url, { signal: controller.signal }).catch((error): null => {
|
||||
console.error(error);
|
||||
|
||||
return null;
|
||||
}),
|
||||
new Promise<null>((resolve): void => {
|
||||
timeoutId = setTimeout((): void => {
|
||||
timeoutId = null;
|
||||
controller?.abort();
|
||||
|
||||
resolve(null);
|
||||
}, timeout);
|
||||
})
|
||||
])
|
||||
.finally(() => {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
|
||||
controller = null;
|
||||
timeoutId = null;
|
||||
});
|
||||
}
|
||||
|
||||
export function fetchJson <T> (url: string, timeout?: number): Promise<T | null> {
|
||||
return fetchWithTimeout(url, timeout).then<T | null>((r) => r?.json() || null);
|
||||
}
|
||||
|
||||
export function fetchText (url: string, timeout?: number): Promise<string | null> {
|
||||
return fetchWithTimeout(url, timeout).then((r) => r?.text() || null);
|
||||
}
|
||||
Reference in New Issue
Block a user