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:
2026-01-07 13:05:27 +03:00
commit d21bfb1320
5867 changed files with 329019 additions and 0 deletions
+115
View File
@@ -0,0 +1,115 @@
// Copyright 2017-2025 @pezkuwi/app-extrinsics authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { SubmittableExtrinsic } from '@pezkuwi/api/types';
import type { ExtrinsicPayload } from '@pezkuwi/types/interfaces';
import type { Inspect } from '@pezkuwi/types/types';
import type { HexString } from '@pezkuwi/util/types';
import React, { useMemo } from 'react';
import { Columar, Inspect as DecodedInspect, Output, styled } from '@pezkuwi/react-components';
import { u8aToHex } from '@pezkuwi/util';
import { useTranslation } from './translate.js';
interface Props {
className?: string;
extrinsic?: SubmittableExtrinsic<'promise'> | null;
isCall: boolean;
payload?: ExtrinsicPayload | null;
withData?: boolean;
withHash?: boolean;
}
function extract (isCall: boolean, extrinsic?: SubmittableExtrinsic<'promise'> | null, payload?: ExtrinsicPayload | null): [HexString, HexString, Inspect | null] {
if (!extrinsic) {
return ['0x', '0x', null];
}
const u8a = extrinsic.method.toU8a();
let inspect = isCall
? extrinsic.method.inspect()
: extrinsic.inspect();
if (payload) {
const prev = inspect;
inspect = payload.inspect();
inspect.inner?.map((entry, index) => {
if (index === 0) {
// replace the method inner
entry.inner = prev.inner;
entry.outer = undefined;
}
return entry;
});
}
// don't use the built-in hash, we only want to convert once
return [
u8aToHex(u8a),
extrinsic.registry.hash(u8a).toHex(),
inspect
];
}
function Decoded ({ className, extrinsic, isCall, payload, withData = true, withHash = true }: Props): React.ReactElement<Props> | null {
const { t } = useTranslation();
const [hex, hash, inspect] = useMemo(
() => extract(isCall, extrinsic, payload),
[extrinsic, isCall, payload]
);
if (!inspect) {
return null;
}
return (
<StyledColumar
className={className}
isPadded={false}
>
<Columar.Column>
{withData && (
<Output
isDisabled
isTrimmed
label={t('encoded call data')}
value={hex}
withCopy
/>
)}
{withHash && (
<Output
isDisabled
label={t('encoded call hash')}
value={hash}
withCopy
/>
)}
</Columar.Column>
<Columar.Column>
<DecodedInspect
hex={hex}
inspect={inspect}
label={t('encoding details')}
/>
</Columar.Column>
</StyledColumar>
);
}
const StyledColumar = styled(Columar)`
.ui--Column:last-child .ui--Labelled {
padding-left: 0.5rem;
label {
left: 2.05rem; /* 3.55 - 1.5 (diff from padding above) */
}
}
`;
export default React.memo(Decoded);
+170
View File
@@ -0,0 +1,170 @@
// Copyright 2017-2025 @pezkuwi/app-extrinsics authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { SubmittableExtrinsic, SubmittableExtrinsicFunction } from '@pezkuwi/api/types';
import type { Call, ExtrinsicPayload } from '@pezkuwi/types/interfaces';
import type { HexString } from '@pezkuwi/util/types';
import type { DecodedExtrinsic } from './types.js';
import React, { useCallback, useState } from 'react';
import { useParams } from 'react-router-dom';
import { Input, InputExtrinsic, MarkError, styled } from '@pezkuwi/react-components';
import { useApi } from '@pezkuwi/react-hooks';
import { Call as CallDisplay } from '@pezkuwi/react-params';
import { assert, compactToU8a, isHex, u8aConcat, u8aEq } from '@pezkuwi/util';
import Decoded from './Decoded.js';
import { useTranslation } from './translate.js';
interface Props {
className?: string;
defaultValue?: HexString | null;
setLast: (value: DecodedExtrinsic | null) => void;
}
interface ExtrinsicInfo {
decoded: SubmittableExtrinsic<'promise'> | null;
extrinsicCall: Call | null;
extrinsicError: string | null;
extrinsicFn: SubmittableExtrinsicFunction<'promise'> | null;
extrinsicHex: string | null;
extrinsicKey: string;
extrinsicPayload: ExtrinsicPayload | null;
isCall: boolean;
}
const DEFAULT_INFO: ExtrinsicInfo = {
decoded: null,
extrinsicCall: null,
extrinsicError: null,
extrinsicFn: null,
extrinsicHex: null,
extrinsicKey: 'none',
extrinsicPayload: null,
isCall: true
};
function Decoder ({ className, defaultValue, setLast }: Props): React.ReactElement<Props> {
const { encoded } = useParams<{ encoded: string }>();
const [initialValue] = useState(() => defaultValue || encoded);
const { t } = useTranslation();
const { api } = useApi();
const [{ decoded, extrinsicCall, extrinsicError, extrinsicFn, extrinsicKey, extrinsicPayload, isCall }, setExtrinsicInfo] = useState<ExtrinsicInfo>(DEFAULT_INFO);
const _setExtrinsicHex = useCallback(
(hex: string): void => {
try {
assert(isHex(hex), 'Expected a hex-encoded call');
let extrinsicCall: Call;
let extrinsicPayload: ExtrinsicPayload | null = null;
let decoded: SubmittableExtrinsic<'promise'> | null = null;
let isCall = false;
try {
// cater for an extrinsic input
const tx = api.tx(hex);
// ensure that the full data matches here
assert(tx.toHex() === hex, 'Cannot decode data as extrinsic, length mismatch');
decoded = tx;
extrinsicCall = api.createType('Call', decoded.method);
} catch {
try {
// attempt to decode as Call
extrinsicCall = api.createType('Call', hex);
const callHex = extrinsicCall.toHex();
if (callHex === hex) {
// all good, we have a call
isCall = true;
} else if (hex.startsWith(callHex)) {
// this could be an un-prefixed payload...
const prefixed = u8aConcat(compactToU8a(extrinsicCall.encodedLength), hex);
extrinsicPayload = api.createType('ExtrinsicPayload', prefixed);
assert(u8aEq(extrinsicPayload.toU8a(), prefixed), 'Unable to decode data as un-prefixed ExtrinsicPayload');
extrinsicCall = api.createType('Call', extrinsicPayload.method.toHex());
} else {
throw new Error('Unable to decode data as Call, length mismatch in supplied data');
}
} catch {
// final attempt, we try this as-is as a (prefixed) payload
extrinsicPayload = api.createType('ExtrinsicPayload', hex);
assert(extrinsicPayload.toHex() === hex, 'Unable to decode input data as Call, Extrinsic or ExtrinsicPayload');
extrinsicCall = api.createType('Call', extrinsicPayload.method.toHex());
}
}
const { method, section } = api.registry.findMetaCall(extrinsicCall.callIndex);
const extrinsicFn = api.tx[section][method];
const extrinsicKey = extrinsicCall.callIndex.toString();
if (!decoded) {
decoded = extrinsicFn(...extrinsicCall.args);
}
setExtrinsicInfo({ ...DEFAULT_INFO, decoded, extrinsicCall, extrinsicFn, extrinsicHex: hex, extrinsicKey, extrinsicPayload, isCall });
setLast({ call: extrinsicCall, fn: extrinsicFn, hex });
} catch (e) {
setExtrinsicInfo({ ...DEFAULT_INFO, extrinsicError: (e as Error).message });
setLast(null);
}
},
[api, setLast]
);
return (
<StyledDiv className={className}>
<Input
defaultValue={initialValue}
isError={!extrinsicFn}
label={t('hex-encoded call')}
onChange={_setExtrinsicHex}
placeholder={t('0x...')}
/>
{extrinsicError && (
<MarkError content={extrinsicError} />
)}
{extrinsicFn && extrinsicCall && (
<>
<InputExtrinsic
defaultValue={extrinsicFn}
isDisabled
key={`extrinsicKey:${extrinsicKey}`}
label={t('decoded call')}
/>
<CallDisplay
className='details'
value={extrinsicCall}
/>
</>
)}
<Decoded
extrinsic={decoded}
isCall={isCall}
payload={extrinsicPayload}
withData={false}
/>
</StyledDiv>
);
}
const StyledDiv = styled.div`
.ui--Call--toplevel {
margin-top: 0;
}
.ui--Call > .ui--Params.withBorder {
padding-left: 2rem;
}
`;
export default React.memo(Decoder);
+108
View File
@@ -0,0 +1,108 @@
// Copyright 2017-2025 @pezkuwi/app-extrinsics authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { SubmittableExtrinsic, SubmittableExtrinsicFunction } from '@pezkuwi/api/types';
import type { RawParam } from '@pezkuwi/react-params/types';
import type { DecodedExtrinsic } from './types.js';
import React, { useCallback, useState } from 'react';
import { Button, InputAddress, MarkError, TxButton } from '@pezkuwi/react-components';
import { useApi } from '@pezkuwi/react-hooks';
import { Extrinsic } from '@pezkuwi/react-params';
import { BalanceFree } from '@pezkuwi/react-query';
import Decoded from './Decoded.js';
import { useTranslation } from './translate.js';
interface Props {
className?: string;
defaultValue: DecodedExtrinsic | null;
}
interface DefaultExtrinsic {
defaultArgs?: RawParam[];
defaultFn: SubmittableExtrinsicFunction<'promise'>;
}
function extractDefaults (value: DecodedExtrinsic | null, defaultFn: SubmittableExtrinsicFunction<'promise'>): DefaultExtrinsic {
if (!value) {
return { defaultFn };
}
return {
defaultArgs: value.call.args.map((value) => ({
isValid: true,
value
})),
defaultFn: value.fn
};
}
function Selection ({ className, defaultValue }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { apiDefaultTxSudo } = useApi();
const [accountId, setAccountId] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
const [extrinsic, setExtrinsic] = useState<SubmittableExtrinsic<'promise'> | null>(null);
const [{ defaultArgs, defaultFn }] = useState<DefaultExtrinsic>(() => extractDefaults(defaultValue, apiDefaultTxSudo));
const _onExtrinsicChange = useCallback(
(method?: SubmittableExtrinsic<'promise'>) =>
setExtrinsic(() => method || null),
[]
);
const _onExtrinsicError = useCallback(
(error?: Error | null) =>
setError(error ? error.message : null),
[]
);
return (
<div className={className}>
<InputAddress
label={t('using the selected account')}
labelExtra={
<BalanceFree
label={<label>{t('free balance')}</label>}
params={accountId}
/>
}
onChange={setAccountId}
type='account'
/>
<Extrinsic
defaultArgs={defaultArgs}
defaultValue={defaultFn}
label={t('submit the following extrinsic')}
onChange={_onExtrinsicChange}
onError={_onExtrinsicError}
/>
<Decoded
extrinsic={extrinsic}
isCall
/>
{error && !extrinsic && (
<MarkError content={error} />
)}
<Button.Group>
<TxButton
extrinsic={extrinsic}
icon='sign-in-alt'
isUnsigned
label={t('Submit Unsigned')}
withSpinner
/>
<TxButton
accountId={accountId}
extrinsic={extrinsic}
icon='sign-in-alt'
label={t('Submit Transaction')}
/>
</Button.Group>
</div>
);
}
export default React.memo(Selection);
+67
View File
@@ -0,0 +1,67 @@
// Copyright 2017-2025 @pezkuwi/app-extrinsics authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { AppProps as Props, TabItem } from '@pezkuwi/react-components/types';
import type { DecodedExtrinsic } from './types.js';
import React, { useRef, useState } from 'react';
import { Route, Routes } from 'react-router';
import { Tabs } from '@pezkuwi/react-components';
import Decoder from './Decoder.js';
import Submission from './Submission.js';
import { useTranslation } from './translate.js';
function createItemsRef (t: (key: string, options?: { replace: Record<string, unknown> }) => string): TabItem[] {
return [
{
isRoot: true,
name: 'create',
text: t('Submission')
},
{
hasParams: true,
name: 'decode',
text: t('Decode')
}
];
}
function ExtrinsicsApp ({ basePath }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [decoded, setDecoded] = useState<DecodedExtrinsic | null>(null);
const itemsRef = useRef(createItemsRef(t));
return (
<main className='extrinsics--App'>
<Tabs
basePath={basePath}
items={itemsRef.current}
/>
<Routes>
<Route path={basePath}>
<Route
element={
<Decoder
defaultValue={decoded?.hex}
setLast={setDecoded}
/>
}
path='decode/:encoded?'
/>
<Route
element={
<Submission defaultValue={decoded} />
}
index
/>
</Route>
</Routes>
</main>
);
}
export { ExtrinsicsApp };
export default React.memo(ExtrinsicsApp);
@@ -0,0 +1,8 @@
// Copyright 2017-2025 @pezkuwi/app-extrinsics authors & contributors
// SPDX-License-Identifier: Apache-2.0
import { useTranslation as useTranslationBase } from 'react-i18next';
export function useTranslation (): { t: (key: string, options?: { replace: Record<string, unknown> }) => string } {
return useTranslationBase('app-extrinsics');
}
+12
View File
@@ -0,0 +1,12 @@
// Copyright 2017-2025 @pezkuwi/app-extrinsics authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { SubmittableExtrinsicFunction } from '@pezkuwi/api/types';
import type { Call } from '@pezkuwi/types/interfaces';
import type { HexString } from '@pezkuwi/util/types';
export interface DecodedExtrinsic {
call: Call;
hex: HexString;
fn: SubmittableExtrinsicFunction<'promise'>;
}