@polkadot/util#compactAddLength TypeScript Examples
The following examples show how to use
@polkadot/util#compactAddLength.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: InputWasm.tsx From crust-apps with Apache License 2.0 | 6 votes |
function InputWasm ({ onChange, ...props }: Props): React.ReactElement<Props> {
const _onChange = useCallback(
(wasm: Uint8Array, name: string): void => {
const isValid = isWasm(wasm);
onChange(compactAddLength(wasm), isValid, name);
},
[onChange]
);
return (
<InputFile
{...props}
accept='application/wasm'
onChange={_onChange}
/>
);
}
Example #2
Source File: KeyValue.tsx From crust-apps with Apache License 2.0 | 6 votes |
// eslint-disable-next-line @typescript-eslint/ban-types
export function createParam (hex: string | String, length = -1): StateParam {
let u8a;
try {
u8a = hexToU8a(hex.toString());
} catch (error) {
u8a = new Uint8Array([]);
}
const isValid = length !== -1
? u8a.length === length
: u8a.length !== 0;
return {
isValid,
u8a: compactAddLength(u8a)
};
}
Example #3
Source File: InputWasm.tsx From subscan-multisig-react with Apache License 2.0 | 6 votes |
function InputWasm({ onChange, ...props }: Props): React.ReactElement<Props> {
const _onChange = useCallback(
(wasm: Uint8Array, name: string): void => {
const isValid = isWasm(wasm);
onChange(compactAddLength(wasm), isValid, name);
},
[onChange]
);
return <InputFile {...props} accept="application/wasm" onChange={_onChange} />;
}
Example #4
Source File: KeyValue.tsx From subscan-multisig-react with Apache License 2.0 | 6 votes |
// eslint-disable-next-line @typescript-eslint/ban-types
export function createParam(hex: string | String, length = -1): StateParam {
let u8a;
try {
u8a = hexToU8a(hex.toString());
} catch (error) {
u8a = new Uint8Array([]);
}
const isValid = length !== -1 ? u8a.length === length : u8a.length !== 0;
return {
isValid,
u8a: compactAddLength(u8a),
};
}
Example #5
Source File: RegisterThread.tsx From crust-apps with Apache License 2.0 | 5 votes |
function RegisterThread ({ className, onClose }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const [accountId, setAccountId] = useState<string | null>(null);
const [paraId, setParaId] = useState<BN | undefined>();
const [{ isWasmValid, wasm }, setWasm] = useState<CodeState>({ isWasmValid: false, wasm: null });
const [genesisState, setGenesisState] = useState<Uint8Array | null>(null);
const _setGenesisState = useCallback(
(data: Uint8Array) => setGenesisState(compactAddLength(data)),
[]
);
const _setWasm = useCallback(
(wasm: Uint8Array, isWasmValid: boolean) => setWasm({ isWasmValid, wasm }),
[]
);
return (
<Modal
className={className}
header={t<string>('Register parathread')}
size='large'
>
<Modal.Content>
<Modal.Columns hint={t<string>('This account will be associated with the parachain and pay the deposit.')}>
<InputAddress
label={t<string>('register from')}
onChange={setAccountId}
type='account'
value={accountId}
/>
</Modal.Columns>
<Modal.Columns hint={t<string>('The id of this parachain as known on the network')}>
<InputNumber
autoFocus
isZeroable={false}
label={t<string>('parachain id')}
onChange={setParaId}
/>
</Modal.Columns>
<Modal.Columns hint={t<string>('The WASM validation function for this parachain.')}>
<InputWasm
help={t<string>('The compiled runtime WASM for the parachain you wish to register.')}
isError={!isWasmValid}
label={t<string>('code')}
onChange={_setWasm}
placeholder={wasm && !isWasmValid && t<string>('The code is not recognized as being in valid WASM format')}
/>
</Modal.Columns>
<Modal.Columns hint={t<string>('The genesis state for this parachain.')}>
<InputFile
help={t<string>('The genesis state for the parachain.')}
isError={!genesisState}
label={t<string>('initial state')}
onChange={_setGenesisState}
/>
</Modal.Columns>
</Modal.Content>
<Modal.Actions onCancel={onClose}>
<TxButton
accountId={accountId}
icon='plus'
isDisabled={!isWasmValid || !genesisState || !paraId?.gt(BN_ZERO)}
onStart={onClose}
params={[paraId, genesisState, wasm]}
tx={api.tx.registrar.register}
/>
</Modal.Actions>
</Modal>
);
}
Example #6
Source File: Raw.tsx From crust-apps with Apache License 2.0 | 5 votes |
function Raw ({ onAdd }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [{ isValid, key }, setValue] = useState<{ isValid: boolean; key: Uint8Array }>({ isValid: false, key: new Uint8Array([]) });
const _onAdd = useCallback(
(): void => {
isValid && onAdd({ isConst: false, key });
},
[isValid, key, onAdd]
);
const _onChangeKey = useCallback(
(key: string): void => {
const u8a = u8aToU8a(key);
setValue({
isValid: u8a.length !== 0,
key: compactAddLength(u8a)
});
},
[]
);
return (
<section className='storage--actionrow'>
<div className='storage--actionrow-value'>
<Input
autoFocus
label={t<string>('hex-encoded storage key')}
onChange={_onChangeKey}
onEnter={_onAdd}
/>
</div>
<div className='storage--actionrow-buttons'>
<Button
icon='plus'
isDisabled={!isValid}
onClick={_onAdd}
/>
</div>
</section>
);
}
Example #7
Source File: BaseBytes.tsx From crust-apps with Apache License 2.0 | 5 votes |
function BaseBytes ({ asHex, children, className = '', defaultValue: { value }, isDisabled, isError, label, length = -1, onChange, onEnter, onEscape, size = 'full', validate = defaultValidate, withCopy, withLabel, withLength }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [defaultValue] = useState(
value
? isDisabled && isU8a(value) && isAscii(value)
? u8aToString(value)
: isHex(value)
? value
: u8aToHex(value as Uint8Array, isDisabled ? 256 : -1)
: undefined
);
const [isValid, setIsValid] = useState(false);
const _onChange = useCallback(
(hex: string): void => {
let [isValid, value] = convertInput(hex);
isValid = isValid && validate(value) && (
length !== -1
? value.length === length
: value.length !== 0
);
if (withLength && isValid) {
value = compactAddLength(value);
}
onChange && onChange({
isValid,
value: asHex
? u8aToHex(value)
: value
});
setIsValid(isValid);
},
[asHex, length, onChange, validate, withLength]
);
return (
<Bare className={className}>
<Input
className={size}
defaultValue={defaultValue as string}
isAction={!!children}
isDisabled={isDisabled}
isError={isError || !isValid}
label={label}
onChange={_onChange}
onEnter={onEnter}
onEscape={onEscape}
placeholder={t<string>('0x prefixed hex, e.g. 0x1234 or ascii data')}
type='text'
withEllipsis
withLabel={withLabel}
>
{children}
{withCopy && (
<CopyButton value={defaultValue} />
)}
</Input>
</Bare>
);
}
Example #8
Source File: Bytes.tsx From crust-apps with Apache License 2.0 | 5 votes |
function Bytes ({ className = '', defaultValue, isDisabled, isError, label, name, onChange, onEnter, onEscape, type, withLabel }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [isValid, setIsValid] = useState(false);
const [isFileDrop, setFileInput] = useState(false);
const _onChangeFile = useCallback(
(value: Uint8Array): void => {
const isValid = value.length !== 0;
onChange && onChange({
isValid,
value: compactAddLength(value)
});
setIsValid(isValid);
},
[onChange]
);
return (
<div className={className}>
{!isDisabled && isFileDrop
? (
<File
isDisabled={isDisabled}
isError={isError || !isValid}
label={label}
onChange={_onChangeFile}
withLabel={withLabel}
/>
)
: (
<BaseBytes
defaultValue={defaultValue}
isDisabled={isDisabled}
isError={isError}
label={label}
length={-1}
name={name}
onChange={onChange}
onEnter={onEnter}
onEscape={onEscape}
type={type}
withLabel={withLabel}
withLength
/>
)
}
{!isDisabled && (
<Toggle
isOverlay
label={t<string>('file upload')}
onChange={setFileInput}
value={isFileDrop}
/>
)}
</div>
);
}
Example #9
Source File: index.ts From contracts-ui with GNU General Public License v3.0 | 5 votes |
export function encodeSalt(salt: Uint8Array | string | null = randomAsU8a()): Uint8Array {
return salt instanceof Bytes
? salt
: salt && salt.length
? compactAddLength(u8aToU8a(salt))
: EMPTY_SALT;
}
Example #10
Source File: getDeriveAccount.ts From parity-bridges-ui with GNU General Public License v3.0 | 5 votes |
export default function getDeriveAccount({ ss58Format = 42, bridgeId, address }: Data): string {
if (!address) {
return address;
}
const input = [...compactAddLength(stringToU8a(accountDerivation)), ...bridgeId, ...decodeAddress(address)];
return encodeAddress(blake2AsHex(Uint8Array.from(input)), ss58Format);
}
Example #11
Source File: BaseBytes.tsx From subscan-multisig-react with Apache License 2.0 | 5 votes |
function BaseBytes({
asHex,
children,
className = '',
defaultValue: { value },
isDisabled,
isError,
label,
length = -1,
onChange,
onEnter,
onEscape,
size = 'full',
validate = defaultValidate,
withCopy,
withLabel,
withLength,
}: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [defaultValue] = useState(
value
? isDisabled && isU8a(value) && isAscii(value)
? u8aToString(value)
: isHex(value)
? value
: // eslint-disable-next-line no-magic-numbers
u8aToHex(value as Uint8Array, isDisabled ? 256 : -1)
: undefined
);
const [isValid, setIsValid] = useState(false);
const _onChange = useCallback(
(hex: string): void => {
let [beValid, val] = convertInput(hex);
beValid = beValid && validate(val) && (length !== -1 ? val.length === length : val.length !== 0);
if (withLength && beValid) {
val = compactAddLength(val);
}
// eslint-disable-next-line
onChange &&
onChange({
isValid: beValid,
value: asHex ? u8aToHex(val) : val,
});
setIsValid(beValid);
},
[asHex, length, onChange, validate, withLength]
);
return (
<Bare className={className}>
<Input
className={size}
defaultValue={defaultValue as string}
isAction={!!children}
isDisabled={isDisabled}
isError={isError || !isValid}
label={label}
onChange={_onChange}
onEnter={onEnter}
onEscape={onEscape}
placeholder={t<string>('0x prefixed hex, e.g. 0x1234 or ascii data')}
type="text"
withEllipsis
withLabel={withLabel}
>
{children}
{withCopy && <CopyButton value={defaultValue} />}
</Input>
</Bare>
);
}
Example #12
Source File: Bytes.tsx From subscan-multisig-react with Apache License 2.0 | 5 votes |
function Bytes({
className = '',
defaultValue,
isDisabled,
isError,
label,
name,
onChange,
onEnter,
onEscape,
type,
withLabel,
}: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [isValid, setIsValid] = useState(false);
const [isFileDrop, setFileInput] = useState(false);
const _onChangeFile = useCallback(
(value: Uint8Array): void => {
const beValid = value.length !== 0;
// eslint-disable-next-line
onChange &&
onChange({
isValid: beValid,
value: compactAddLength(value),
});
setIsValid(beValid);
},
[onChange]
);
return (
<div className={className}>
{!isDisabled && isFileDrop ? (
<File
isDisabled={isDisabled}
isError={isError || !isValid}
label={label}
onChange={_onChangeFile}
withLabel={withLabel}
/>
) : (
<BaseBytes
defaultValue={defaultValue}
isDisabled={isDisabled}
isError={isError}
label={label}
length={-1}
name={name}
onChange={onChange}
onEnter={onEnter}
onEscape={onEscape}
type={type}
withLabel={withLabel}
withLength
/>
)}
{!isDisabled && <Toggle isOverlay label={t<string>('file upload')} onChange={setFileInput} value={isFileDrop} />}
</div>
);
}
Example #13
Source File: Propose.tsx From crust-apps with Apache License 2.0 | 4 votes |
function Propose ({ className, onClose }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const [accountId, setAccountId] = useState<string | null>(null);
const [name, setName] = useState('');
const [paraId, setParaId] = useState<BN | undefined>();
const [balance, setBalance] = useState(() => BN_THOUSAND.mul(BN_TEN.pow(new BN(api.registry.chainDecimals[0]))));
const [validators, setValidators] = useState<string[]>(['']);
const [{ isWasmValid, wasm }, setWasm] = useState<CodeState>({ isWasmValid: false, wasm: null });
const [genesisState, setGenesisState] = useState<Uint8Array | null>(null);
const _setGenesisState = useCallback(
(data: Uint8Array) => setGenesisState(compactAddLength(data)),
[]
);
const _setWasm = useCallback(
(wasm: Uint8Array, isWasmValid: boolean) => setWasm({ isWasmValid, wasm }),
[]
);
const _setAddress = useCallback(
(index: number, address: string) =>
setValidators((v) => v.map((v, i) => i === index ? address : v)),
[]
);
const _addValidator = useCallback(
() => setValidators((v) => [...v, '']),
[]
);
const _delValidator = useCallback(
() => setValidators((v) => [...v.slice(0, v.length - 1)]),
[]
);
const isNameValid = name.length >= 3;
const isValDuplicate = validators.some((a, ai) => validators.some((b, bi) => ai !== bi && a === b));
return (
<Modal
className={className}
header={t<string>('Propose parachain')}
size='large'
>
<Modal.Content>
<Modal.Columns hint={t<string>('This account will be associated with the parachain and pay the deposit.')}>
<InputAddress
label={t<string>('propose from')}
onChange={setAccountId}
type='account'
value={accountId}
/>
</Modal.Columns>
<Modal.Columns hint={t<string>('The name for this parachain, the id and the allocated/requested balance.')}>
<Input
autoFocus
isError={!isNameValid}
label={t<string>('parachain name')}
onChange={setName}
/>
<InputNumber
isZeroable={false}
label={t<string>('requested id')}
onChange={setParaId}
/>
<InputBalance
defaultValue={balance}
label={t<string>('initial balance')}
onChange={setBalance}
/>
</Modal.Columns>
<Modal.Columns hint={t<string>('The WASM validation function as well as the genesis state for this parachain.')}>
<InputWasm
help={t<string>('The compiled runtime WASM for the parachain you wish to register.')}
isError={!isWasmValid}
label={t<string>('validation code')}
onChange={_setWasm}
placeholder={wasm && !isWasmValid && t<string>('The code is not recognized as being in valid WASM format')}
/>
<InputFile
help={t<string>('The genesis state for the parachain.')}
isError={!genesisState}
label={t<string>('genesis state')}
onChange={_setGenesisState}
/>
</Modal.Columns>
<Modal.Columns hint={t<string>('The validators for this parachain. At least one is required and where multiple is supplied, they need to be unique.')}>
{validators.map((address, index) => (
<Validator
address={address}
index={index}
key={index}
setAddress={_setAddress}
t={t}
/>
))}
{!validators.length && (
<MarkWarning content={t<string>('You need to supply at last one running validator for your parachain alongside this request.')} />
)}
{isValDuplicate && (
<MarkWarning content={t<string>('You have duplicated validator entries, ensure each is unique.')} />
)}
<Button.Group>
<Button
icon='plus'
label={t<string>('Add validator')}
onClick={_addValidator}
/>
<Button
icon='minus'
isDisabled={validators.length === 0}
label={t<string>('Remove validator')}
onClick={_delValidator}
/>
</Button.Group>
</Modal.Columns>
</Modal.Content>
<Modal.Actions onCancel={onClose}>
<TxButton
accountId={accountId}
icon='plus'
isDisabled={!isWasmValid || !genesisState || !isNameValid || !validators.length || !paraId?.gt(BN_ZERO)}
onStart={onClose}
params={[paraId, name, wasm, genesisState, validators, balance]}
tx={api.tx.proposeParachain?.proposeParachain}
/>
</Modal.Actions>
</Modal>
);
}
Example #14
Source File: useEstimatedFeePayload.ts From parity-bridges-ui with GNU General Public License v3.0 | 4 votes |
useEstimatedFeePayload = (
transactionState: TransactionState,
dispatchTransaction: Dispatch<TransactionsActionType>
) => {
const { createType, stateCall } = useApiCallsContext();
const laneId = useLaneId();
const sourceTargetDetails = useSourceTarget();
const {
sourceChainDetails: {
chain: sourceChain,
apiConnection: { api: sourceApi }
},
targetChainDetails: {
apiConnection: { api: targetApi },
chain: targetChain
}
} = sourceTargetDetails;
const { account, senderAccountBalance, senderCompanionAccountBalance } = useAccountContext();
const { action, isBridged } = useGUIContext();
const { estimatedFeeMethodName } = getSubstrateDynamicNames(targetChain);
const previousPayloadEstimatedFeeLoading = usePrevious(transactionState.payloadEstimatedFeeLoading);
const { bridgedMessages } = getSubstrateDynamicNames(targetChain);
const dispatch = useCallback(
(error: string | null, data: PayloadEstimatedFee | null, loading: boolean) =>
dispatchTransaction(
TransactionActionCreators.setPayloadEstimatedFee({
payloadEstimatedFeeError: error,
payloadEstimatedFee: data,
payloadEstimatedFeeLoading: loading,
sourceTargetDetails,
createType,
isBridged,
senderAccountBalance,
senderCompanionAccountBalance,
chainDecimals: targetApi.registry.chainDecimals[0]
})
),
[
createType,
dispatchTransaction,
isBridged,
senderAccountBalance,
senderCompanionAccountBalance,
sourceTargetDetails,
targetApi.registry.chainDecimals
]
);
const calculateFeeAndPayload = useCallback(
async (currentTransactionState: TransactionState) => {
if (currentTransactionState.action === TransactionTypes.INTERNAL_TRANSFER) {
const { estimatedFee, weight } = await getFeeAndWeightForInternals({
api: sourceApi,
transactionState: currentTransactionState
});
const payload = {
sourceAccount: currentTransactionState.senderAccount,
transferAmount: currentTransactionState.transferAmount!.toNumber(),
receiverAddress: currentTransactionState.receiverAddress,
weight
};
return { estimatedSourceFee: estimatedFee, payload };
}
const { call, weight } = await getTransactionCallWeight({
action,
account,
targetApi,
transactionState: currentTransactionState
});
if (!call || !weight) {
return emptyData;
}
const callToCompact = currentTransactionState.action === TransactionTypes.CUSTOM ? call : call.slice(2);
const payload = {
call: compactAddLength(callToCompact),
origin: {
SourceAccount: account!.addressRaw
},
dispatch_fee_payment: currentTransactionState.payFee,
spec_version: targetApi.consts.system.version.specVersion.toNumber(),
weight
};
const payloadType = createType(sourceChain as keyof InterfaceTypes, 'OutboundPayload', payload);
logger.info(`OutboundPayload: ${JSON.stringify(payload)}`);
logger.info(`OutboundPayload.toHex(): ${payloadType.toHex()}`);
const messageFeeType = createType(sourceChain as keyof InterfaceTypes, 'MessageFeeData', {
lane_id: laneId,
payload: payloadType.toHex()
});
// estimatedFeeMessageDelivery
const estimatedFeeCall = await stateCall(sourceChain, estimatedFeeMethodName, messageFeeType.toHex());
const estimatedFeeType = createType(sourceChain as keyof InterfaceTypes, 'Option<Balance>', estimatedFeeCall);
const estimatedFeeMessageDelivery = estimatedFeeType.toString();
// estimatedFeeBridgeCall
const bridgeMessage = sourceApi.tx[bridgedMessages].sendMessage(laneId, payload, estimatedFeeCall);
const submitMessageTransactionFee = await sourceApi.rpc.payment.queryFeeDetails(bridgeMessage.toHex());
const estimatedFeeBridgeCallBalance = (submitMessageTransactionFee as FeeDetails).inclusionFee.unwrap()
.adjustedWeightFee;
const estimatedFeeBridgeCall = estimatedFeeBridgeCallBalance.toString();
// estimatedSourceFee calculation based on the sum of estimatedFeeMessageDelivery + estimatedFeeBridgeCallBalance
const estimatedSourceFeeBN = new BN(estimatedFeeMessageDelivery).add(estimatedFeeBridgeCallBalance.toBn());
const estimatedSourceFee = estimatedSourceFeeBN.toString();
// estimatedTargetFee
const targetFeeDetails = await targetApi.rpc.payment.queryFeeDetails(u8aToHex(call));
const estimatedTargetFee = (targetFeeDetails as FeeDetails).inclusionFee.unwrap().adjustedWeightFee.toString();
return {
estimatedSourceFee,
estimatedFeeMessageDelivery,
estimatedFeeBridgeCall,
estimatedTargetFee,
payload
};
},
[
account,
action,
bridgedMessages,
createType,
estimatedFeeMethodName,
laneId,
sourceApi,
sourceChain,
stateCall,
targetApi
]
);
useEffect(() => {
const { shouldEvaluatePayloadEstimatedFee, payloadEstimatedFeeLoading } = transactionState;
if (shouldEvaluatePayloadEstimatedFee && payloadEstimatedFeeLoading) {
logger.info(
'Transaction information changed while estimated fee is being calculating. Batching the new calculation.'
);
dispatchTransaction(TransactionActionCreators.setBatchedEvaluationPayloadEstimatedFee(transactionState));
}
if (shouldEvaluatePayloadEstimatedFee && !payloadEstimatedFeeLoading) {
genericCall({
//@ts-ignore
call: () => calculateFeeAndPayload(transactionState),
dispatch,
emptyData
});
}
}, [calculateFeeAndPayload, dispatch, dispatchTransaction, transactionState]);
useEffect(() => {
const { batchedTransactionState, payloadEstimatedFeeLoading } = transactionState;
if (
previousPayloadEstimatedFeeLoading &&
!payloadEstimatedFeeLoading &&
batchedTransactionState &&
senderAccountBalance &&
senderCompanionAccountBalance
) {
genericCall({
//@ts-ignore
call: () => calculateFeeAndPayload(batchedTransactionState),
dispatch,
emptyData
});
dispatchTransaction(TransactionActionCreators.setBatchedEvaluationPayloadEstimatedFee(null));
}
}, [
account,
calculateFeeAndPayload,
dispatch,
dispatchTransaction,
previousPayloadEstimatedFeeLoading,
senderAccountBalance,
senderCompanionAccountBalance,
transactionState
]);
}
Example #15
Source File: transactionReducer.test.ts From parity-bridges-ui with GNU General Public License v3.0 | 4 votes |
describe('transactionReducer', () => {
describe('SET_RECEIVER', () => {
const payload = {
unformattedReceiverAddress: '',
sourceChainDetails,
targetChainDetails,
isBridged: true
};
describe('Bridge', () => {
it('should return the according transaction state for a companion address and its corresponding companion account.', () => {
payload.unformattedReceiverAddress = '5rERgaT1Z8nM3et2epA5i1VtEBfp5wkhwHtVE8HK7BRbjAH2';
const action = TransactionActionCreators.setReceiver(payload);
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
derivedReceiverAccount: '714dr3fW9PAKWMRn9Zcr6vtqn8gUEoKF7E2bDu5BniTMS4bo',
receiverAddress: '5rERgaT1Z8nM3et2epA5i1VtEBfp5wkhwHtVE8HK7BRbjAH2',
unformattedReceiverAddress: '5rERgaT1Z8nM3et2epA5i1VtEBfp5wkhwHtVE8HK7BRbjAH2',
showBalance: true,
formatFound: 'chain1',
transactionReadyToExecute: false,
payloadEstimatedFeeLoading: false,
shouldEvaluatePayloadEstimatedFee: false,
estimatedSourceFee: null,
estimatedFeeMessageDelivery: null,
estimatedFeeBridgeCall: null,
estimatedTargetFee: null
});
});
it('should return the according transaction state for a target native address.', () => {
payload.unformattedReceiverAddress = '74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5';
const action = TransactionActionCreators.setReceiver(payload);
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
receiverAddress: '74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5',
unformattedReceiverAddress: '74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5',
showBalance: true,
formatFound: 'chain2',
transactionReadyToExecute: false,
shouldEvaluatePayloadEstimatedFee: false
});
});
it('should return the according transaction state for a generic address.', () => {
payload.unformattedReceiverAddress = '5H3ZryLmpNwrochemdVFTq9WMJW39NCo5HWFEwRtjbVtrThD';
const action = TransactionActionCreators.setReceiver(payload);
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
genericReceiverAccount: '5H3ZryLmpNwrochemdVFTq9WMJW39NCo5HWFEwRtjbVtrThD',
unformattedReceiverAddress: '5H3ZryLmpNwrochemdVFTq9WMJW39NCo5HWFEwRtjbVtrThD',
formatFound: 'GENERIC',
transactionReadyToExecute: false,
shouldEvaluatePayloadEstimatedFee: false,
estimatedSourceFee: null,
estimatedFeeMessageDelivery: null,
estimatedFeeBridgeCall: null,
estimatedTargetFee: null
});
});
it('should return the according transaction state for an invalid address.', () => {
payload.unformattedReceiverAddress = 'invalid';
const action = TransactionActionCreators.setReceiver(payload);
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
unformattedReceiverAddress: 'invalid',
addressValidationError: 'Invalid address',
formatFound: 'INCORRECT_FORMAT',
transactionReadyToExecute: false,
shouldEvaluatePayloadEstimatedFee: false
});
});
it('should return the according transaction state for unsupported prefix provided.', () => {
payload.unformattedReceiverAddress = 'tH95Ew4kVD9VcwsyXaSdC74Noe3H8o6fJfnKhZezXHKHEcs';
const action = TransactionActionCreators.setReceiver(payload);
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
unformattedReceiverAddress: 'tH95Ew4kVD9VcwsyXaSdC74Noe3H8o6fJfnKhZezXHKHEcs',
addressValidationError: 'Unsupported address SS58 prefix: 8',
formatFound: '8',
transactionReadyToExecute: false,
shouldEvaluatePayloadEstimatedFee: false
});
});
});
describe('Local', () => {
it('should return the according transaction state for native address.', () => {
payload.unformattedReceiverAddress = '5smXQvbC88CDjy8SCpmPjEk4EDMoUTyvCvq2w3HhWj4pYQqz';
payload.isBridged = false;
const action = TransactionActionCreators.setReceiver(payload);
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
unformattedReceiverAddress: payload.unformattedReceiverAddress,
receiverAddress: payload.unformattedReceiverAddress,
genericReceiverAccount: null,
addressValidationError: null,
showBalance: true,
formatFound: payload.sourceChainDetails.chain
});
});
it('should return the according transaction state for generic address.', () => {
payload.unformattedReceiverAddress = '5H3ZryLmpNwrochemdVFTq9WMJW39NCo5HWFEwRtjbVtrThD';
payload.isBridged = false;
const action = TransactionActionCreators.setReceiver(payload);
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
unformattedReceiverAddress: payload.unformattedReceiverAddress,
receiverAddress: '5smXQvbC88CDjy8SCpmPjEk4EDMoUTyvCvq2w3HhWj4pYQqz',
genericReceiverAccount: null,
addressValidationError: null,
showBalance: true,
formatFound: GENERIC
});
});
it('should return invalid account.', () => {
payload.unformattedReceiverAddress = '74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5';
payload.isBridged = false;
const action = TransactionActionCreators.setReceiver(payload);
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
unformattedReceiverAddress: payload.unformattedReceiverAddress,
addressValidationError: 'Invalid Address',
receiverAddress: null,
genericReceiverAccount: null,
showBalance: false,
formatFound: null
});
});
});
});
describe('SET_PAYLOAD_ESTIMATED_FEE', () => {
type PayloadEstimatedFee = {
payload: TransactionPayload | null;
estimatedSourceFee: string | null;
estimatedFeeMessageDelivery: string | null;
estimatedFeeBridgeCall: string | null;
estimatedTargetFee: string | null;
};
let payloadEstimatedFeeError: string | null;
let payloadEstimatedFee: PayloadEstimatedFee;
let payloadEstimatedFeeLoading: boolean;
beforeEach(() => {
payloadEstimatedFeeError = null;
payloadEstimatedFee = {
estimatedSourceFee: null,
estimatedFeeMessageDelivery: null,
estimatedFeeBridgeCall: null,
estimatedTargetFee: null,
payload: null
};
payloadEstimatedFeeLoading = false;
(getTransactionDisplayPayload as jest.Mock).mockReturnValue({
payloadHex: null,
transactionDisplayPayload: null
});
});
it('should return initial state regarding estimated fee', () => {
const action = TransactionActionCreators.setPayloadEstimatedFee({
payloadEstimatedFeeError,
payloadEstimatedFee,
payloadEstimatedFeeLoading,
sourceTargetDetails: {} as SourceTargetState,
//@ts-ignore
createType: () => 'type',
isBridged: true,
senderAccountBalance: null,
senderCompanionAccountBalance: null,
chainDecimals: 9
});
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
estimatedSourceFee: null,
estimatedFeeMessageDelivery: null,
estimatedFeeBridgeCall: null,
estimatedTargetFee: null,
payloadEstimatedFeeError: null,
payloadEstimatedFeeLoading: false,
payload: null,
transactionReadyToExecute: false
});
});
it('should return loading estimated fee', () => {
const payloadEstimatedFeeLoading = true;
const action = TransactionActionCreators.setPayloadEstimatedFee({
payloadEstimatedFeeError,
payloadEstimatedFee,
payloadEstimatedFeeLoading,
sourceTargetDetails: {} as SourceTargetState,
//@ts-ignore
createType: () => 'type',
isBridged: true,
senderAccountBalance: null,
senderCompanionAccountBalance: null,
chainDecimals: 9
});
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
estimatedSourceFee: null,
estimatedFeeMessageDelivery: null,
estimatedFeeBridgeCall: null,
estimatedTargetFee: null,
payloadEstimatedFeeError: null,
payloadEstimatedFeeLoading: true,
payload: null,
transactionReadyToExecute: false,
payloadHex: null,
transactionDisplayPayload: null
});
});
it('should return corresponding error state for estimated fee', () => {
payloadEstimatedFeeError = 'Error';
const action = TransactionActionCreators.setPayloadEstimatedFee({
payloadEstimatedFeeError,
payloadEstimatedFee,
payloadEstimatedFeeLoading,
sourceTargetDetails: {} as SourceTargetState,
//@ts-ignore
createType: () => 'type',
isBridged: true,
senderAccountBalance: null,
senderCompanionAccountBalance: null,
chainDecimals: 9
});
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
estimatedSourceFee: null,
estimatedFeeMessageDelivery: null,
estimatedFeeBridgeCall: null,
estimatedTargetFee: null,
payloadEstimatedFeeError,
payloadEstimatedFeeLoading: false,
payload: null,
transactionReadyToExecute: false,
payloadHex: null,
transactionDisplayPayload: null
});
});
it('should return corresponding error state for estimated fee', () => {
payloadEstimatedFeeError = 'Error';
const action = TransactionActionCreators.setPayloadEstimatedFee({
payloadEstimatedFeeError,
payloadEstimatedFee,
payloadEstimatedFeeLoading,
sourceTargetDetails: {} as SourceTargetState,
//@ts-ignore
createType: () => 'type',
isBridged: true,
senderAccountBalance: null,
senderCompanionAccountBalance: null,
chainDecimals: 9
});
const result = transactionReducer(state, action);
expect(result).toEqual({
...state,
estimatedSourceFee: null,
estimatedFeeMessageDelivery: null,
estimatedFeeBridgeCall: null,
estimatedTargetFee: null,
payloadEstimatedFeeError,
payloadEstimatedFeeLoading: false,
payload: null,
transactionReadyToExecute: false,
payloadHex: null,
transactionDisplayPayload: null
});
});
it('should return corresponding estimated fee, payload and all the necessary conditions to execute the transaction', () => {
const payloadHex = 'payloadHexMode';
const createType = jest.fn();
const payload = {
call: compactAddLength(new Uint8Array([0, 0, 0, 0])),
origin: {
SourceAccount: new Uint8Array([0, 0, 0, 0])
},
spec_version: 1,
weight: 1234
};
const transactionDisplayPayload = { payload };
(getTransactionDisplayPayload as jest.Mock).mockReturnValue({
payloadHex,
transactionDisplayPayload
});
const estimatedSourceFee = '1234';
const estimatedFeeMessageDelivery = '1234';
const estimatedFeeBridgeCall = '1234';
const estimatedTargetFee = '1234';
payloadEstimatedFee = {
estimatedSourceFee,
estimatedFeeMessageDelivery,
estimatedFeeBridgeCall,
estimatedTargetFee,
payload
};
const sourceTargetDetails = {} as SourceTargetState;
const action = TransactionActionCreators.setPayloadEstimatedFee({
payloadEstimatedFeeError,
payloadEstimatedFee,
payloadEstimatedFeeLoading,
sourceTargetDetails,
//@ts-ignore
createType: () => 'type',
isBridged: true,
senderAccountBalance: null,
senderCompanionAccountBalance: null,
chainDecimals: 9
});
const newState = { ...state };
newState.action = TransactionTypes.TRANSFER;
newState.transferAmount = new BN(1);
newState.receiverAddress = '74GNQjmkcfstRftSQPJgMREchqHM56EvAUXRc266cZ1NYVW5';
newState.senderAccount = '5rERgaT1Z8nM3et2epA5i1VtEBfp5wkhwHtVE8HK7BRbjAH2';
const result = transactionReducer(newState, action);
expect(result).toEqual({
...newState,
estimatedSourceFee,
estimatedFeeMessageDelivery,
estimatedFeeBridgeCall,
estimatedTargetFee,
payloadEstimatedFeeError: null,
payloadEstimatedFeeLoading: false,
payload,
transactionReadyToExecute: true,
payloadHex,
transactionDisplayPayload
});
});
});
});