mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-07-08 18:17:23 +00:00
971df8edba
- Remove all 3rd party parachain configurations from endpoints: - productionRelayPolkadot.ts: Keep only system parachains - productionRelayDicle.ts: Keep only system parachains - testingRelayZagros.ts: Keep only system parachains - testingRelayTeyrChain.ts: Keep only system parachains - Update domain references: - polkadot.js.org → pezkuwichain.app - wiki.polkadot.network → wiki.pezkuwichain.io - dotapps.io → pezkuwichain.app - statement.polkadot.network → docs.pezkuwichain.io/statement - support.polkadot.network → docs.pezkuwichain.io - Update repository references: - github.com/pezkuwi-js/apps → github.com/pezkuwichain/pwap - Rename system parachains to Pezkuwi ecosystem: - PolkadotAssetHub → PezkuwiAssetHub - polkadotBridgeHub → pezkuwiBridgeHub - polkadotCollectives → pezkuwiCollectives - polkadotCoretime → pezkuwiCoretime - polkadotPeople → pezkuwiPeople - Update network name in claims utility: - Polkadot → Pezkuwi
171 lines
5.5 KiB
TypeScript
171 lines
5.5 KiB
TypeScript
// Copyright 2017-2026 @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);
|