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
@@ -0,0 +1,111 @@
// Copyright 2017-2025 @pezkuwi/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
// we use augmented types in this tsconfig
import '@pezkuwi/api-augment/bizinikiwi';
import type { DispatchError, DispatchResult, Event, EventRecord } from '@pezkuwi/types/interfaces';
import type { StagingXcmV5TraitsOutcome } from '@pezkuwi/types/lookup';
type EventCheck = (event: Event) => string | null;
const INCOMPLETE = 'incomplete execution';
function extractError (result: DispatchResult): string | null {
if (!result) {
return INCOMPLETE;
} else if (result.isErr) {
return `error: ${getDispatchError(result.asErr)}`;
}
return null;
}
function batchInterrupted ({ data: [index, error] }: Event): string | null {
return `error: ${index.toString()}: ${getDispatchError(error as DispatchError)}`;
}
function dispatchResult ({ data: [result] }: Event): string | null {
return extractError(result as DispatchResult);
}
function dispatchResultCouncil ({ data: [, result] }: Event): string | null {
return extractError(result as DispatchResult);
}
// [approving, timepoint, multisig, callHash, result]
function dispatchResultMulti ({ data: [,,,, result] }: Event): string | null {
return extractError(result as DispatchResult);
}
function xcmAttempted ({ data: [outcome] }: Event): string | null {
if (!outcome) {
return INCOMPLETE;
} else if ((outcome as StagingXcmV5TraitsOutcome).isIncomplete) {
const error = (outcome as StagingXcmV5TraitsOutcome).asIncomplete.error;
return `error: ${error.error.type}`;
}
return null;
}
const collective: Record<string, EventCheck> = {
Executed: dispatchResultCouncil
};
const xcmPallet: Record<string, EventCheck> = {
Attempted: xcmAttempted
};
const CHECKS: Record<string, Record<string, EventCheck>> = {
allianceMotion: collective,
council: collective,
membership: collective,
multisig: {
MultisigExecuted: dispatchResultMulti
},
pezkuwiXcm: xcmPallet,
proxy: {
ProxyExecuted: dispatchResult
},
sudo: {
Sudid: dispatchResult,
SudoAsDone: dispatchResult
},
technicalCommittee: collective,
utility: {
BatchInterrupted: batchInterrupted,
DispatchedAs: dispatchResult
},
xcmPallet
};
export function getDispatchError (dispatchError: DispatchError): string {
let message: string = dispatchError.type;
if (dispatchError.isModule) {
try {
const mod = dispatchError.asModule;
const error = dispatchError.registry.findMetaError(mod);
message = `${error.section}.${error.name}`;
} catch {
// swallow
}
} else if (dispatchError.isToken) {
message = `${dispatchError.type}.${dispatchError.asToken.type}`;
}
return message;
}
export function getIncompleteMessage ({ event }: EventRecord): string | null {
const { method, section } = event;
return (
!!CHECKS[section] &&
!!CHECKS[section][method] &&
CHECKS[section][method](event)
);
}
@@ -0,0 +1,11 @@
// Copyright 2017-2025 @pezkuwi/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { QueueTxStatus } from './types.js';
export const STATUS_COMPLETE: QueueTxStatus[] = [
// status from subscription
'finalitytimeout', 'finalized', 'inblock', 'usurped', 'dropped', 'invalid',
// normal completion
'cancelled', 'error', 'sent'
];
@@ -0,0 +1,312 @@
// Copyright 2017-2025 @pezkuwi/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { IconName } from '@fortawesome/fontawesome-svg-core';
import type { QueueStatus, QueueTx, QueueTxStatus } from './types.js';
import React, { useEffect, useState } from 'react';
import { useQueue } from '@pezkuwi/react-hooks';
import AddressMini from '../AddressMini.js';
import Icon from '../Icon.js';
import Spinner from '../Spinner.js';
import { styled } from '../styled.js';
import { STATUS_COMPLETE } from './constants.js';
interface Props {
className?: string;
}
function iconName (status: string): IconName {
switch (status) {
case 'error':
return 'ban';
case 'event':
case 'eventWarn':
return 'assistive-listening-systems';
case 'received':
return 'telegram-plane';
default:
return 'check';
}
}
function signerIconName (status: QueueTxStatus): IconName {
switch (status) {
case 'cancelled':
return 'ban';
case 'completed':
case 'inblock':
case 'finalized':
case 'sent':
return 'check';
case 'dropped':
case 'invalid':
case 'usurped':
return 'arrow-down';
case 'error':
case 'finalitytimeout':
return 'exclamation-triangle';
case 'queued':
// case 'retracted':
return 'random';
default:
return 'spinner';
}
}
function renderStatus ({ account, action, id, message, removeItem, status }: QueueStatus): React.ReactNode {
return (
<div
className={`item ${status}`}
key={id}
>
<div className='wrapper'>
<div className='container'>
<Icon
icon='times'
onClick={removeItem}
/>
<div className='short'>
<Icon icon={iconName(status)} />
</div>
<div className='desc'>
<div className='header'>
{Array.isArray(action)
? action.map((action, index) => <div key={index}>{action}</div>)
: action}
</div>
{account && (
<AddressMini value={account} />
)}
<div className='status'>
{message}
</div>
</div>
</div>
</div>
</div>
);
}
function renderItem ({ error, extrinsic, id, removeItem, rpc, status }: QueueTx): React.ReactNode {
let { method, section } = rpc;
if (extrinsic) {
const found = extrinsic.registry.findMetaCall(extrinsic.callIndex);
if (found.section !== 'unknown') {
method = found.method;
section = found.section;
}
}
const icon = signerIconName(status) as 'ban' | 'spinner';
return (
<div
className={`item ${status}`}
key={id}
>
<div className='wrapper'>
<div className='container'>
{STATUS_COMPLETE.includes(status) && (
<Icon
icon='times'
onClick={removeItem}
/>
)}
<div className='short'>
{icon === 'spinner'
? <Spinner variant='push' />
: <Icon icon={icon} />
}
</div>
<div className='desc'>
<div className='header'>
{section}.{method}
</div>
<div className='status'>
{error ? (error.message || error.toString()) : status}
</div>
</div>
</div>
</div>
</div>
);
}
function filterSt (stqueue?: QueueStatus[]): QueueStatus[] {
return (stqueue || []).filter(({ isCompleted }) => !isCompleted);
}
function filterTx (txqueue?: QueueTx[]): QueueTx[] {
return (txqueue || []).filter(({ status }) => !['completed', 'incomplete'].includes(status));
}
function Status ({ className = '' }: Props): React.ReactElement<Props> | null {
const { stqueue, txqueue } = useQueue();
const [allSt, setAllSt] = useState<QueueStatus[]>([]);
const [allTx, setAllTx] = useState<QueueTx[]>([]);
useEffect((): void => {
setAllSt(filterSt(stqueue));
}, [stqueue]);
useEffect((): void => {
setAllTx(filterTx(txqueue));
}, [txqueue]);
if (!allSt.length && !allTx.length) {
return null;
}
return (
<StyledDiv className={`${className} ui--Status`}>
{allTx.map(renderItem)}
{allSt.map(renderStatus)}
</StyledDiv>
);
}
const StyledDiv = styled.div`
display: inline-block;
overflow: hidden;
position: fixed;
right: 0.75rem;
top: 0.75rem;
transition-property: width;
transition-duration: 0.75s;
width: 4.5rem;
z-index: 1001;
&:hover {
transform: scale(1);
width: 23rem;
.item .desc {
display: block;
}
}
.item {
display: block;
.desc {
display: none;
}
> .wrapper > .container {
align-items: top;
background: #00688b;
border-radius: 0.25rem;
color: white;
display: flex;
justify-content: space-between;
margin-bottom: 0.25rem;
padding: 0 0.5rem;
vertical-align: middle;
position: relative;
.desc {
flex: 1;
overflow: hidden;
padding: 0.75rem 1rem 0.5rem;
width: 19rem;
.status {
font-weight: var(--font-weight-normal);
}
.ui--AddressMini {
.ui--AddressMini-address {
min-width: 0;
text-align: left;
}
}
}
.header {
opacity: 0.66;
}
.short {
font-size: 2.5rem;
min-width: 3rem;
opacity: 0.75;
padding: 0.5rem 0 0.5rem 0.5rem;
.ui--Icon {
color: white !important;
line-height: 1;
}
.ui--Spinner {
display: inline-block;
height: 1em;
line-height: 1;
vertical-align: -0.125em;
img {
height: 1em;
width: 1em;
}
}
}
.padded {
padding: 0.25rem 0 0 0 !important;
}
.ui--Icon.isClickable {
position: absolute;
top: 0.5rem;
right: 0.5rem;
cursor: pointer;
}
}
&.cancelled > .wrapper > .container {
background: #cd9b1d
}
&.event > .wrapper > .container {
background: teal;
}
&.eventWarn > .wrapper > .container {
background: darkorange;
}
&.completed,
&.finalized,
&.inblock,
&.sent,
&.success {
& > .wrapper > .container {
background: green;
}
}
&.dropped,
&.error,
&.finalitytimeout,
&.invalid,
&.usurped {
& > .wrapper > .container {
background: red;
}
}
}
`;
export default React.memo(Status);
@@ -0,0 +1,115 @@
// Copyright 2017-2025 @pezkuwi/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0
import type { SubmittableResult } from '@pezkuwi/api';
import type { SubmittableExtrinsic } from '@pezkuwi/api/promise/types';
import type { SignerResult } from '@pezkuwi/api/types';
import type { AccountId, Address } from '@pezkuwi/types/interfaces';
import type { DefinitionRpcExt, Registry, SignerPayloadJSON } from '@pezkuwi/types/types';
export type Actions = 'create' | 'edit' | 'restore' | 'forget' | 'backup' | 'changePassword' | 'transfer';
export interface ActionStatusBase {
account?: AccountId | Address | string;
message?: string;
status: 'error' | 'event' | 'eventWarn' | 'queued' | 'received' | 'success';
}
export interface ActionStatusPartial extends ActionStatusBase {
action: string;
}
export interface ActionStatus extends ActionStatusBase {
action: string | string[];
}
export interface AccountInfo {
accountId?: string | null;
}
export type QueueTxStatus = 'future' | 'ready' | 'finalized' | 'finalitytimeout' | 'usurped' | 'dropped' | 'inblock' | 'invalid' | 'broadcast' | 'cancelled' | 'completed' | 'error' | 'incomplete' | 'queued' | 'qr' | 'retracted' | 'sending' | 'signing' | 'sent' | 'blocked';
export type SignerCallback = (id: number, result: SignerResult | null) => void;
export type TxCallback = (status: SubmittableResult) => void;
export type TxFailedCallback = (status: Error | SubmittableResult | null) => void;
export interface QueueTx extends AccountInfo {
error?: Error;
extrinsic?: SubmittableExtrinsic;
id: number;
isUnsigned?: boolean;
payload?: SignerPayloadJSON;
result?: any;
removeItem: () => void;
rpc: DefinitionRpcExt;
signerCb?: SignerCallback;
txFailedCb?: TxFailedCallback;
txSuccessCb?: TxCallback;
txStartCb?: () => void;
txUpdateCb?: TxCallback;
values?: unknown[];
status: QueueTxStatus;
}
export interface QueueStatus extends ActionStatus {
id: number;
isCompleted: boolean;
removeItem: () => void;
}
export interface QueueTxResult {
error?: Error;
result?: any;
status: QueueTxStatus;
}
export interface QueueTxExtrinsic extends AccountInfo {
extrinsic?: SubmittableExtrinsic;
}
export interface QueueTxRpc extends AccountInfo {
rpc: DefinitionRpcExt;
values: unknown[];
}
export interface PartialAccountInfo {
accountId?: string | null;
}
export interface PartialQueueTxExtrinsic extends PartialAccountInfo {
extrinsic?: SubmittableExtrinsic;
payload?: SignerPayloadJSON;
signerCb?: SignerCallback;
txFailedCb?: TxFailedCallback;
txSuccessCb?: TxCallback;
txStartCb?: () => void;
txUpdateCb?: TxCallback;
isUnsigned?: boolean;
}
export interface PartialQueueTxRpc extends PartialAccountInfo {
rpc: DefinitionRpcExt;
values: unknown[];
}
export type QueueTxRpcAdd = (value: PartialQueueTxRpc) => void;
export type QueueTxExtrinsicAdd = (value: PartialQueueTxExtrinsic) => void;
export type QueueTxPayloadAdd = (registry: Registry, payload: SignerPayloadJSON, signerCb: SignerCallback) => void;
export type QueueTxMessageSetStatus = (id: number, status: QueueTxStatus, result?: any, error?: Error) => void;
export type QueueAction$Add = (status: ActionStatus | ActionStatus[]) => void;
export interface QueueProps {
stqueue: QueueStatus[];
txqueue: QueueTx[];
queueAction: QueueAction$Add;
queueExtrinsic: QueueTxExtrinsicAdd;
queuePayload: QueueTxPayloadAdd;
queueRpc: QueueTxRpcAdd;
queueSetTxStatus: QueueTxMessageSetStatus;
}