mirror of
https://github.com/pezkuwichain/pezkuwi-apps.git
synced 2026-06-15 22:01:06 +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,136 @@
|
||||
// Copyright 2017-2025 @pezkuwi/app-staking authors & contributors
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import type { ApiPromise } from '@pezkuwi/api';
|
||||
import type { ContractPromise } from '@pezkuwi/api-contract';
|
||||
import type { ContractCallOutcome } from '@pezkuwi/api-contract/types';
|
||||
import type { SignedBlockExtended } from '@pezkuwi/api-derive/types';
|
||||
import type { ContractLink } from './types.js';
|
||||
|
||||
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { Table } from '@pezkuwi/react-components';
|
||||
import { useApi, useCall } from '@pezkuwi/react-hooks';
|
||||
import { formatNumber } from '@pezkuwi/util';
|
||||
|
||||
import { useTranslation } from '../translate.js';
|
||||
import Call from './Call.js';
|
||||
import Contract from './Contract.js';
|
||||
import { getContractForAddress } from './util.js';
|
||||
|
||||
export interface Props {
|
||||
contracts: string[];
|
||||
updated: number;
|
||||
}
|
||||
|
||||
interface Indexes {
|
||||
contractIndex: number;
|
||||
messageIndex: number;
|
||||
onCallResult?: (messageIndex: number, result?: ContractCallOutcome) => void;
|
||||
}
|
||||
|
||||
function filterContracts (api: ApiPromise, keyringContracts: string[] = []): ContractPromise[] {
|
||||
return keyringContracts
|
||||
.map((address) => getContractForAddress(api, address.toString()))
|
||||
.filter((contract): contract is ContractPromise => !!contract);
|
||||
}
|
||||
|
||||
function ContractsTable ({ contracts: keyringContracts }: Props): React.ReactElement<Props> {
|
||||
const { t } = useTranslation();
|
||||
const { api } = useApi();
|
||||
const newBlock = useCall<SignedBlockExtended>(api.derive.chain.subscribeNewBlocks);
|
||||
const [{ contractIndex, messageIndex, onCallResult }, setIndexes] = useState<Indexes>({ contractIndex: 0, messageIndex: 0 });
|
||||
const [isCallOpen, setIsCallOpen] = useState(false);
|
||||
const [contractLinks, setContractLinks] = useState<Record<string, ContractLink[]>>({});
|
||||
|
||||
const headerRef = useRef<[string?, string?, number?][]>([
|
||||
[t('contracts'), 'start'],
|
||||
[undefined, undefined, 3],
|
||||
[t('status'), 'start'],
|
||||
[]
|
||||
]);
|
||||
|
||||
useEffect((): void => {
|
||||
if (newBlock) {
|
||||
const exts = newBlock.block.extrinsics
|
||||
.filter(({ method }) => api.tx.contracts.call.is(method))
|
||||
.map(({ args }): ContractLink | null => {
|
||||
const contractId = keyringContracts.find((a) => args[0].eq(a));
|
||||
|
||||
if (!contractId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
blockHash: newBlock.block.header.hash.toHex(),
|
||||
blockNumber: formatNumber(newBlock.block.header.number),
|
||||
contractId
|
||||
};
|
||||
})
|
||||
.filter((value): value is ContractLink => !!value);
|
||||
|
||||
exts.length && setContractLinks((links): Record<string, ContractLink[]> => {
|
||||
exts.forEach((value): void => {
|
||||
links[value.contractId] = [value].concat(links[value.contractId] || []).slice(0, 3);
|
||||
});
|
||||
|
||||
return { ...links };
|
||||
});
|
||||
}
|
||||
}, [api, keyringContracts, newBlock]);
|
||||
|
||||
const contracts = useMemo(
|
||||
() => filterContracts(api, keyringContracts),
|
||||
[api, keyringContracts]
|
||||
);
|
||||
|
||||
const _toggleCall = useCallback(
|
||||
() => setIsCallOpen((isCallOpen) => !isCallOpen),
|
||||
[]
|
||||
);
|
||||
|
||||
const _onCall = useCallback(
|
||||
(contractIndex: number, messageIndex: number, onCallResult: (messageIndex: number, result?: ContractCallOutcome) => void): void => {
|
||||
setIndexes({ contractIndex, messageIndex, onCallResult });
|
||||
setIsCallOpen(true);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const _setMessageIndex = useCallback(
|
||||
(messageIndex: number) => setIndexes((state) => ({ ...state, messageIndex })),
|
||||
[]
|
||||
);
|
||||
|
||||
const contract = contracts[contractIndex] || null;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Table
|
||||
empty={t('No contracts available')}
|
||||
header={headerRef.current}
|
||||
>
|
||||
{contracts.map((contract, index): React.ReactNode => (
|
||||
<Contract
|
||||
contract={contract}
|
||||
index={index}
|
||||
key={contract.address.toString()}
|
||||
links={contractLinks[contract.address.toString()]}
|
||||
onCall={_onCall}
|
||||
/>
|
||||
))}
|
||||
</Table>
|
||||
{isCallOpen && contract && (
|
||||
<Call
|
||||
contract={contract}
|
||||
messageIndex={messageIndex}
|
||||
onCallResult={onCallResult}
|
||||
onChangeMessage={_setMessageIndex}
|
||||
onClose={_toggleCall}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default React.memo(ContractsTable);
|
||||
Reference in New Issue
Block a user