Rebrand: polkadot → pezkuwi, substrate → bizinikiwi, kusama → dicle

This commit is contained in:
2026-01-07 02:29:40 +03:00
commit d5f038faea
1383 changed files with 1088018 additions and 0 deletions
@@ -0,0 +1,70 @@
// Copyright 2017-2025 @pezkuwi/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
import type { JsonRpcResponse } from '../types.js';
import { RpcCoder } from './index.js';
describe('decodeResponse', (): void => {
let coder: RpcCoder;
beforeEach((): void => {
coder = new RpcCoder();
});
it('expects a non-empty input object', (): void => {
expect(
() => coder.decodeResponse(undefined as unknown as JsonRpcResponse<unknown>)
).toThrow(/Invalid jsonrpc/);
});
it('expects a valid jsonrpc field', (): void => {
expect(
() => coder.decodeResponse({} as JsonRpcResponse<unknown>)
).toThrow(/Invalid jsonrpc/);
});
it('expects a valid id field', (): void => {
expect(
() => coder.decodeResponse({ jsonrpc: '2.0' } as JsonRpcResponse<unknown>)
).toThrow(/Invalid id/);
});
it('expects a valid result field', (): void => {
expect(
() => coder.decodeResponse({ id: 1, jsonrpc: '2.0' } as JsonRpcResponse<unknown>)
).toThrow(/No result/);
});
it('throws any error found', (): void => {
expect(
() => coder.decodeResponse({ error: { code: 123, message: 'test error' }, id: 1, jsonrpc: '2.0' } as JsonRpcResponse<unknown>)
).toThrow(/123: test error/);
});
it('throws any error found, with data', (): void => {
expect(
() => coder.decodeResponse({ error: { code: 123, data: 'Error("Some random error description")', message: 'test error' }, id: 1, jsonrpc: '2.0' } as JsonRpcResponse<unknown>)
).toThrow(/123: test error: Some random error description/);
});
it('allows for number subscription ids', (): void => {
expect(
coder.decodeResponse({ id: 1, jsonrpc: '2.0', method: 'test', params: { result: 'test result', subscription: 1 } } as JsonRpcResponse<unknown>)
).toEqual('test result');
});
it('allows for string subscription ids', (): void => {
expect(
coder.decodeResponse({ id: 1, jsonrpc: '2.0', method: 'test', params: { result: 'test result', subscription: 'abc' } } as JsonRpcResponse<unknown>)
).toEqual('test result');
});
it('returns the result', (): void => {
expect(
coder.decodeResponse({ id: 1, jsonrpc: '2.0', result: 'some result' } as JsonRpcResponse<unknown>)
).toEqual('some result');
});
});
@@ -0,0 +1,20 @@
// Copyright 2017-2025 @pezkuwi/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
import { RpcCoder } from './index.js';
describe('encodeJson', (): void => {
let coder: RpcCoder;
beforeEach((): void => {
coder = new RpcCoder();
});
it('encodes a valid JsonRPC JSON string', (): void => {
expect(
coder.encodeJson('method', ['params'])
).toEqual([1, '{"id":1,"jsonrpc":"2.0","method":"method","params":["params"]}']);
});
});
@@ -0,0 +1,25 @@
// Copyright 2017-2025 @pezkuwi/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
import { RpcCoder } from './index.js';
describe('encodeObject', (): void => {
let coder: RpcCoder;
beforeEach((): void => {
coder = new RpcCoder();
});
it('encodes a valid JsonRPC object', (): void => {
expect(
coder.encodeObject('method', ['a', 'b'])
).toEqual([1, {
id: 1,
jsonrpc: '2.0',
method: 'method',
params: ['a', 'b']
}]);
});
});
@@ -0,0 +1,111 @@
// Copyright 2017-2025 @pezkuwi/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
/// <reference types="@pezkuwi/dev-test/globals.d.ts" />
import { isError } from '@pezkuwi/util';
import RpcError from './error.js';
describe('RpcError', (): void => {
describe('constructor', (): void => {
it('constructs an Error that is still an Error', (): void => {
expect(
isError(
new RpcError()
)
).toEqual(true);
});
});
describe('static', (): void => {
it('exposes the .CODES as a static', (): void => {
expect(
Object.keys(RpcError.CODES)
).not.toEqual(0);
});
});
describe('constructor properties', (): void => {
it('sets the .message property', (): void => {
expect(
new RpcError('test message').message
).toEqual('test message');
});
it("sets the .message to '' when not set", (): void => {
expect(
new RpcError().message
).toEqual('');
});
it('sets the .code property', (): void => {
expect(
new RpcError('test message', 1234).code
).toEqual(1234);
});
it('sets the .code to UKNOWN when not set', (): void => {
expect(
new RpcError('test message').code
).toEqual(RpcError.CODES.UNKNOWN);
});
it('sets the .data property', (): void => {
const data = 'here';
expect(
new RpcError('test message', 1234, data).data
).toEqual(data);
});
it('sets the .data property to generic value', (): void => {
const data = { custom: 'value' } as const;
expect(
new RpcError('test message', 1234, data).data
).toEqual(data);
});
});
describe('stack traces', (): void => {
// eslint-disable-next-line @typescript-eslint/ban-types
let captureStackTrace: (targetObject: Record<string, any>, constructorOpt?: Function | undefined) => void;
beforeEach((): void => {
captureStackTrace = Error.captureStackTrace;
Error.captureStackTrace = function (error): void {
Object.defineProperty(error, 'stack', {
configurable: true,
get: function getStack (): string {
const value = 'some stack returned';
Object.defineProperty(this, 'stack', { value });
return value;
}
});
};
});
afterEach((): void => {
Error.captureStackTrace = captureStackTrace;
});
it('captures via captureStackTrace when available', (): void => {
expect(
new RpcError().stack
).toEqual('some stack returned');
});
it('captures via stack when captureStackTrace not available', (): void => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Error.captureStackTrace = null as any;
expect(
new RpcError().stack.length
).not.toEqual(0);
});
});
});
+66
View File
@@ -0,0 +1,66 @@
// Copyright 2017-2025 @pezkuwi/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { RpcErrorInterface } from '../types.js';
import { isFunction } from '@pezkuwi/util';
const UNKNOWN = -99999;
function extend<Data, K extends keyof RpcError<Data>> (that: RpcError<Data>, name: K, value: RpcError<Data>[K]): void {
Object.defineProperty(that, name, {
configurable: true,
enumerable: false,
value
});
}
/**
* @name RpcError
* @summary Extension to the basic JS Error.
* @description
* The built-in JavaScript Error class is extended by adding a code to allow for Error categorization. In addition to the normal `stack`, `message`, the numeric `code` and `data` (any types) parameters are available on the object.
* @example
* <BR>
*
* ```javascript
* const { RpcError } from '@pezkuwi/util');
*
* throw new RpcError('some message', RpcError.CODES.METHOD_NOT_FOUND); // => error.code = -32601
* ```
*/
export default class RpcError<T = never> extends Error implements RpcErrorInterface<T> {
public code!: number;
public data?: T;
public override message!: string;
public override name!: string;
public override stack!: string;
public constructor (message = '', code: number = UNKNOWN, data?: T) {
super();
extend(this, 'message', String(message));
extend(this, 'name', this.constructor.name);
extend(this, 'data', data);
extend(this, 'code', code);
if (isFunction(Error.captureStackTrace)) {
Error.captureStackTrace(this, this.constructor);
} else {
const { stack } = new Error(message);
stack && extend(this, 'stack', stack);
}
}
public static CODES = {
ASSERT: -90009,
INVALID_JSONRPC: -99998,
METHOD_NOT_FOUND: -32601, // Rust client
UNKNOWN
};
}
+88
View File
@@ -0,0 +1,88 @@
// Copyright 2017-2025 @pezkuwi/rpc-provider authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { JsonRpcRequest, JsonRpcResponse, JsonRpcResponseBaseError } from '../types.js';
import { isNumber, isString, isUndefined, stringify } from '@pezkuwi/util';
import RpcError from './error.js';
function formatErrorData (data?: string | number): string {
if (isUndefined(data)) {
return '';
}
const formatted = `: ${isString(data)
? data.replace(/Error\("/g, '').replace(/\("/g, '(').replace(/"\)/g, ')').replace(/\(/g, ', ').replace(/\)/g, '')
: stringify(data)}`;
// We need some sort of cut-off here since these can be very large and
// very nested, pick a number and trim the result display to it
return formatted.length <= 256
? formatted
: `${formatted.substring(0, 255)}`;
}
function checkError (error?: JsonRpcResponseBaseError): void {
if (error) {
const { code, data, message } = error;
throw new RpcError(`${code}: ${message}${formatErrorData(data)}`, code, data);
}
}
/** @internal */
export class RpcCoder {
#id = 0;
public decodeResponse <T> (response?: JsonRpcResponse<T>): T {
if (!response || response.jsonrpc !== '2.0') {
throw new Error('Invalid jsonrpc field in decoded object');
}
const isSubscription = !isUndefined(response.params) && !isUndefined(response.method);
if (
!isNumber(response.id) &&
(
!isSubscription || (
!isNumber(response.params.subscription) &&
!isString(response.params.subscription)
)
)
) {
throw new Error('Invalid id field in decoded object');
}
checkError(response.error);
if (response.result === undefined && !isSubscription) {
throw new Error('No result found in jsonrpc response');
}
if (isSubscription) {
checkError(response.params.error);
return response.params.result;
}
return response.result;
}
public encodeJson (method: string, params: unknown[]): [number, string] {
const [id, data] = this.encodeObject(method, params);
return [id, stringify(data)];
}
public encodeObject (method: string, params: unknown[]): [number, JsonRpcRequest] {
const id = ++this.#id;
return [id, {
id,
jsonrpc: '2.0',
method,
params
}];
}
}