@polkadot/util#BN_HUNDRED TypeScript Examples
The following examples show how to use
@polkadot/util#BN_HUNDRED.
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: BountyActionMessage.tsx From crust-apps with Apache License 2.0 | 5 votes |
function BountyActionMessage ({ bestNumber, blocksUntilUpdate, status }: Props): JSX.Element {
const { t } = useTranslation();
const { unlockAt } = useBountyStatus(status);
const { bountyUpdatePeriod } = useBounties();
const blocksUntilPayout = useMemo(() => unlockAt?.sub(bestNumber), [bestNumber, unlockAt]);
const blocksPercentageLeftToShowWarning = bountyUpdatePeriod?.muln(BLOCKS_PERCENTAGE_LEFT_TO_SHOW_WARNING).div(BN_HUNDRED);
const blocksToShowWarning = blocksPercentageLeftToShowWarning ?? BLOCKS_LEFT_TO_SHOW_WARNING;
return (
<div>
{blocksUntilUpdate?.lte(BN_ZERO) && (
<BountyInfo
description={t<string>('Update overdue')}
type='warning'
/>
)}
{blocksUntilUpdate?.lt(blocksToShowWarning) && blocksUntilUpdate?.gt(BN_ZERO) && (
<BountyInfo
description={t<string>('Close deadline')}
type='warning'
/>
)}
{status.isApproved && (
<BountyInfo
description={t<string>('Waiting for Bounty Funding')}
type='info'
/>
)}
{status.isCuratorProposed && (
<BountyInfo
description={t<string>("Waiting for Curator's acceptance")}
type='info'
/>
)}
{blocksUntilPayout?.lt(BN_ZERO) &&
<BountyInfo
description={t<string>('Waiting for implementer to claim')}
type='info'
/>
}
</div>
);
}
Example #2
Source File: index.tsx From crust-apps with Apache License 2.0 | 5 votes |
function applyFilter (validators: ValidatorInfo[], medianComm: number, allIdentity: Record<string, DeriveHasIdentity>, { daysPayout, isBabe, maxPaid, withElected, withGroup, withIdentity, withPayout, withoutComm, withoutOver }: Flags, nominatedBy?: Record<string, NominatedBy[]>): ValidatorInfo[] {
const displays: (string[])[] = [];
const parentIds: string[] = [];
return validators.filter(({ accountId, commissionPer, isElected, isFavorite, lastPayout, numNominators }): boolean => {
if (isFavorite) {
return true;
}
const stashId = accountId.toString();
const thisIdentity = allIdentity[stashId];
const nomCount = numNominators || nominatedBy?.[stashId]?.length || 0;
if (
(!withElected || isElected) &&
(!withIdentity || !!thisIdentity?.hasIdentity) &&
(!withPayout || !isBabe || (!!lastPayout && daysPayout.gte(lastPayout))) &&
(!withoutComm || (
MAX_COMM_PERCENT > 0
? (commissionPer >= MAX_COMM_PERCENT)
: (!medianComm || (commissionPer < medianComm)))
) &&
(!withoutOver || !maxPaid || maxPaid.muln(MAX_CAP_PERCENT).div(BN_HUNDRED).gten(nomCount))
) {
if (!withGroup) {
return true;
} else if (!thisIdentity || !thisIdentity.hasIdentity) {
parentIds.push(stashId);
return true;
} else if (!thisIdentity.parentId) {
if (!parentIds.includes(stashId)) {
if (thisIdentity.display) {
const sanitized = thisIdentity.display
.replace(/[^\x20-\x7E]/g, '')
.replace(/-/g, ' ')
.replace(/_/g, ' ')
.split(' ')
.map((p) => p.trim())
.filter((v) => !!v);
displays.push(sanitized);
}
parentIds.push(stashId);
return true;
}
} else {
parentIds.push(thisIdentity.parentId);
return true;
}
}
return false;
});
}
Example #3
Source File: useSortedTargets.ts From crust-apps with Apache License 2.0 | 5 votes |
function extractInfo (api: ApiPromise, allAccounts: string[], electedDerive: DeriveStakingElected, waitingDerive: DeriveStakingWaiting, favorites: string[], totalIssuance: BN, lastEraInfo: LastEra, validatorStakeLimit: ValidatorStakeLimit[], guarantors: Guarantor[], totalReward: BN, validatorCount: number, historyDepth?: BN): Partial<SortedTargets> {
const [elected, nominators] = extractSingle(api, allAccounts, electedDerive, favorites, lastEraInfo, validatorStakeLimit, guarantors, historyDepth);
const [waiting, waitingNominators] = extractSingle(api, allAccounts, waitingDerive, favorites, lastEraInfo, validatorStakeLimit, guarantors);
const electedTotals = elected
.filter(({ isActive }) => isActive)
.map(({ bondTotal }) => bondTotal)
const waitingTotals = waiting
.filter(({ isActive }) => isActive)
.map(({ bondTotal }) => bondTotal)
const activeTotals = [...electedTotals, ...waitingTotals].sort((a, b) => a.cmp(b));
const totalStaked = activeTotals.reduce((total: BN, value) => total.iadd(value), new BN(0));
const avgStaked = totalStaked.divn(activeTotals.length);
const inflation = calcInflation(api, totalStaked, totalIssuance);
// add the explicit stakedReturn
!avgStaked.isZero() && elected.forEach((e): void => {
if (!e.skipRewards) {
const adjusted = avgStaked.mul(BN_HUNDRED).imuln(inflation.stakedReturn).div(e.bondTotal);
// in some cases, we may have overflows... protect against those
// @ts-ignore
e.stakedReturn = Number(adjusted.gt(BN_MAX_INTEGER) ? BN_MAX_INTEGER : adjusted) / BN_HUNDRED.toNumber();
e.stakedReturnCmp = e.stakedReturn * (100 - e.commissionPer) / 100;
}
});
// all validators, calc median commission
const tmpMinNominated = Object.values(nominators).reduce((min: BN, value) => {
return min.isZero() || value.lt(min)
? value
: min;
}, BN_ZERO);
const minNominated = Object.values(waitingNominators).reduce((min: BN, value) => {
return min.isZero() || value.lt(min)
? value
: min;
}, tmpMinNominated);
const validators = sortValidators(arrayFlatten([elected, waiting])).map(e => calculateApy(totalReward, validatorCount, totalStaked, e));
const commValues = validators.map(({ commissionPer }) => commissionPer).sort((a, b) => a - b);
const midIndex = Math.floor(commValues.length / 2);
const medianComm = commValues.length
? commValues.length % 2
? commValues[midIndex]
: (commValues[midIndex - 1] + commValues[midIndex]) / 2
: 0;
// ids
const waitingIds = waiting.map(({ key }) => key);
const validatorIds = arrayFlatten([
elected.map(({ key }) => key),
waitingIds
]);
const nominateIds = arrayFlatten([
elected.filter(({ isBlocking }) => !isBlocking).map(({ key }) => key),
waiting.filter(({ isBlocking }) => !isBlocking).map(({ key }) => key)
]);
return {
avgStaked,
inflation,
lowStaked: activeTotals[0] || BN_ZERO,
medianComm,
minNominated,
nominateIds,
nominators: Object.keys(nominators).concat(Object.keys(waitingNominators).filter((e) => !Object.keys(nominators).includes(e))),
totalIssuance,
totalStaked,
validatorIds,
validators,
waitingIds
};
}
Example #4
Source File: CardSummary.tsx From crust-apps with Apache License 2.0 | 5 votes |
function CardSummary ({ children, className = '', help, label, progress }: Props): React.ReactElement<Props> | null {
const value = progress && progress.value;
const total = progress && progress.total;
const left = progress && !isUndefined(value) && !isUndefined(total) && value.gten(0) && total.gtn(0)
? (
value.gt(total)
? `>${
progress.isPercent
? '100'
: formatNumber(total)
}`
: (
progress.isPercent
? value.mul(BN_HUNDRED).div(total).toString()
: formatNumber(value)
)
)
: undefined;
if (progress && isUndefined(left)) {
return null;
}
const isTimed = progress && progress.withTime && !isUndefined(progress.total);
return (
<article className={className}>
<Labelled
help={help}
isSmall
label={label}
>
{children}{
progress && !progress.hideValue && (
<>
{isTimed && !children && (
<BlockToTime value={progress.total} />
)}
<div className={isTimed ? 'isSecondary' : 'isPrimary'}>
{!left || isUndefined(progress.total)
? '-'
: !isTimed || progress.isPercent || !progress.value
? `${left}${progress.isPercent ? '' : '/'}${
progress.isPercent
? '%'
: formatNumber(progress.total)
}`
: (
<BlockToTime
className='timer'
value={progress.total.sub(progress.value)}
/>
)
}
</div>
</>
)
}
</Labelled>
{progress && !progress.hideGraph && <Progress {...progress} />}
</article>
);
}
Example #5
Source File: CardSummary.tsx From subscan-multisig-react with Apache License 2.0 | 5 votes |
function CardSummary({ children, className = '', help, label, progress }: Props): React.ReactElement<Props> | null {
const value = progress && progress.value;
const total = progress && progress.total;
const left =
progress && !isUndefined(value) && !isUndefined(total) && value.gten(0) && total.gtn(0)
? value.gt(total)
? `>${progress.isPercent ? '100' : formatNumber(total)}`
: progress.isPercent
? value.mul(BN_HUNDRED).div(total).toString()
: formatNumber(value)
: undefined;
if (progress && isUndefined(left)) {
return null;
}
const isTimed = progress && progress.withTime && !isUndefined(progress.total);
return (
<article className={className}>
<Labelled help={help} isSmall label={label}>
{children}
{progress && !progress.hideValue && (
<>
{isTimed && !children && <BlockToTime value={progress.total} />}
<div className={isTimed ? 'isSecondary' : 'isPrimary'}>
{!left || isUndefined(progress.total) ? (
'-'
) : !isTimed || progress.isPercent || !progress.value ? (
`${left}${progress.isPercent ? '' : '/'}${progress.isPercent ? '%' : formatNumber(progress.total)}`
) : (
<BlockToTime className="timer" value={progress.total.sub(progress.value)} />
)}
</div>
</>
)}
</Labelled>
{progress && !progress.hideGraph && <Progress {...progress} />}
</article>
);
}
Example #6
Source File: Transfer.tsx From crust-apps with Apache License 2.0 | 4 votes |
function Transfer ({ className = '', onClose, recipientId: propRecipientId, senderId: propSenderId }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const [amount, setAmount] = useState<BN | undefined>(BN_ZERO);
const [hasAvailable] = useState(true);
const [isProtected, setIsProtected] = useState(true);
const [isAll, setIsAll] = useState(false);
const [[maxTransfer, noFees], setMaxTransfer] = useState<[BN | null, boolean]>([null, false]);
const [recipientId, setRecipientId] = useState<string | null>(null);
const [senderId, setSenderId] = useState<string | null>(null);
const [[, recipientPhish], setPhishing] = useState<[string | null, string | null]>([null, null]);
const balances = useCall<DeriveBalancesAll>(api.derive.balances.all, [propSenderId || senderId]);
const accountInfo = useCall<AccountInfoWithProviders | AccountInfoWithRefCount>(api.query.system.account, [propSenderId || senderId]);
useEffect((): void => {
const fromId = propSenderId || senderId as string;
const toId = propRecipientId || recipientId as string;
if (balances && balances.accountId.eq(fromId) && fromId && toId && isFunction(api.rpc.payment?.queryInfo)) {
setTimeout((): void => {
try {
api.tx.balances
.transfer(toId, balances.availableBalance)
.paymentInfo(fromId)
.then(({ partialFee }): void => {
const adjFee = partialFee.muln(110).div(BN_HUNDRED);
const maxTransfer = balances.availableBalance.sub(adjFee);
setMaxTransfer(
maxTransfer.gt(api.consts.balances.existentialDeposit)
? [maxTransfer, false]
: [null, true]
);
})
.catch(console.error);
} catch (error) {
console.error((error as Error).message);
}
}, 0);
} else {
setMaxTransfer([null, false]);
}
}, [api, balances, propRecipientId, propSenderId, recipientId, senderId]);
useEffect((): void => {
checkPhishing(propSenderId || senderId, propRecipientId || recipientId)
.then(setPhishing)
.catch(console.error);
}, [propRecipientId, propSenderId, recipientId, senderId]);
const noReference = accountInfo
? isRefcount(accountInfo)
? accountInfo.refcount.isZero()
: accountInfo.consumers.isZero()
: true;
const canToggleAll = !isProtected && balances && balances.accountId.eq(propSenderId || senderId) && maxTransfer && noReference;
return (
<Modal
className='app--accounts-Modal'
header={t<string>('Send CRU')}
size='large'
>
<Modal.Content>
<div className={className}>
<Modal.Columns hint={t<string>('The transferred balance will be subtracted (along with fees) from the sender account.')}>
<InputAddress
defaultValue={propSenderId}
help={t<string>('The account you will send funds from.')}
isDisabled={!!propSenderId}
label={t<string>('send from account')}
labelExtra={
<Available
label={t<string>('transferrable')}
params={propSenderId || senderId}
/>
}
onChange={setSenderId}
type='account'
/>
</Modal.Columns>
<Modal.Columns hint={t<string>('The beneficiary will have access to the transferred fees when the transaction is included in a block.')}>
<InputAddress
defaultValue={propRecipientId}
help={t<string>('Select a contact or paste the address you want to send funds to.')}
isDisabled={!!propRecipientId}
label={t<string>('send to address')}
labelExtra={
<Available
label={t<string>('transferrable')}
params={propRecipientId || recipientId}
/>
}
onChange={setRecipientId}
type='allPlus'
/>
{recipientPhish && (
<MarkError content={t<string>('The recipient is associated with a known phishing site on {{url}}', { replace: { url: recipientPhish } })} />
)}
</Modal.Columns>
<Modal.Columns hint={t<string>('If the recipient account is new, the balance needs to be more than the existential deposit. Likewise if the sending account balance drops below the same value, the account will be removed from the state.')}>
{canToggleAll && isAll
? (
<InputBalance
autoFocus
defaultValue={maxTransfer}
help={t<string>('The full account balance to be transferred, minus the transaction fees')}
isDisabled
key={maxTransfer?.toString()}
label={t<string>('transferrable minus fees')}
/>
)
: (
<>
<InputBalance
autoFocus
help={t<string>('Type the amount you want to transfer. Note that you can select the unit on the right e.g sending 1 milli is equivalent to sending 0.001.')}
isError={!hasAvailable}
isZeroable
label={t<string>('amount')}
onChange={setAmount}
/>
<InputBalance
defaultValue={api.consts.balances.existentialDeposit}
help={t<string>('The minimum amount that an account should have to be deemed active')}
isDisabled
label={t<string>('existential deposit')}
/>
</>
)
}
</Modal.Columns>
<Modal.Columns hint={t('With the keep-alive option set, the account is protected against removal due to low balances.')}>
{isFunction(api.tx.balances.transferKeepAlive) && (
<Toggle
className='typeToggle'
label={
isProtected
? t<string>('Transfer with account keep-alive checks')
: t<string>('Normal transfer without keep-alive checks')
}
onChange={setIsProtected}
value={isProtected}
/>
)}
{canToggleAll && (
<Toggle
className='typeToggle'
label={t<string>('Transfer the full account balance, reap the sender')}
onChange={setIsAll}
value={isAll}
/>
)}
{!isProtected && !noReference && (
<MarkWarning content={t<string>('There is an existing reference count on the sender account. As such the account cannot be reaped from the state.')} />
)}
{noFees && (
<MarkWarning content={t<string>('The transaction, after application of the transfer fees, will drop the available balance below the existential deposit. As such the transfer will fail. The account needs more free funds to cover the transaction fees.')} />
)}
</Modal.Columns>
</div>
</Modal.Content>
<Modal.Actions onCancel={onClose}>
<TxButton
accountId={propSenderId || senderId}
icon='paper-plane'
isDisabled={!hasAvailable || !(propRecipientId || recipientId) || !amount || !!recipientPhish}
label={t<string>('Make Transfer')}
onStart={onClose}
params={
canToggleAll && isAll
? [propRecipientId || recipientId, maxTransfer]
: [propRecipientId || recipientId, amount]
}
tx={(isProtected && api.tx.balances.transferKeepAlive) || api.tx.balances.transfer}
/>
</Modal.Actions>
</Modal>
);
}
Example #7
Source File: ProposalCreate.tsx From crust-apps with Apache License 2.0 | 4 votes |
function Propose ({ className }: Props): React.ReactElement<Props> | null {
const { t } = useTranslation();
const { api } = useApi();
const [accountId, setAccountId] = useState<string | null>(null);
const [beneficiary, setBeneficiary] = useState<string | null>(null);
const [isOpen, toggleOpen] = useToggle();
const [value, setValue] = useState<BN | undefined>();
const hasValue = value?.gtn(0);
const bondPercentage = useMemo(
() => `${api.consts.treasury.proposalBond.mul(BN_HUNDRED).div(BN_MILLION).toNumber().toFixed(2)}%`,
[api]
);
return (
<>
{isOpen && (
<Modal
className={className}
header={t<string>('Submit treasury proposal')}
size='large'
>
<Modal.Content>
<Modal.Columns hint={t<string>('This account will make the proposal and be responsible for the bond.')}>
<InputAddress
help={t<string>('Select the account you wish to submit the proposal from.')}
label={t<string>('submit with account')}
onChange={setAccountId}
type='account'
withLabel
/>
</Modal.Columns>
<Modal.Columns hint={t<string>('The beneficiary will receive the full amount if the proposal passes.')}>
<InputAddress
help={t<string>('The account to which the proposed balance will be transferred if approved')}
label={t<string>('beneficiary')}
onChange={setBeneficiary}
type='allPlus'
/>
</Modal.Columns>
<Modal.Columns hint={
<>
<p>{t<string>('The value is the amount that is being asked for and that will be allocated to the beneficiary if the proposal is approved.')}</p>
<p>{t<string>('Of the beneficiary amount, at least {{bondPercentage}} would need to be put up as collateral. The maximum of this and the minimum bond will be used to secure the proposal, refundable if it passes.', { replace: { bondPercentage } })}</p>
</>
}>
<InputBalance
help={t<string>('The amount that will be allocated from the treasury pot')}
isError={!hasValue}
label={t<string>('value')}
onChange={setValue}
/>
<Static
help={t<string>('The on-chain percentage for the treasury')}
label={t<string>('proposal bond')}
>
{bondPercentage}
</Static>
<InputBalance
defaultValue={api.consts.treasury.proposalBondMinimum.toString()}
help={t<string>('The minimum amount that will be bonded')}
isDisabled
label={t<string>('minimum bond')}
/>
<MarkWarning content={t<string>('Be aware that once submitted the proposal will be put to a council vote. If the proposal is rejected due to a lack of info, invalid requirements or non-benefit to the network as a whole, the full bond posted (as describe above) will be lost.')} />
</Modal.Columns>
</Modal.Content>
<Modal.Actions onCancel={toggleOpen}>
<TxButton
accountId={accountId}
icon='plus'
isDisabled={!accountId || !hasValue}
label={t<string>('Submit proposal')}
onStart={toggleOpen}
params={[value, beneficiary]}
tx={api.tx.treasury.proposeSpend}
/>
</Modal.Actions>
</Modal>
)}
<Button
icon='plus'
label={t<string>('Submit proposal')}
onClick={toggleOpen}
/>
</>
);
}
Example #8
Source File: Transfer.tsx From subscan-multisig-react with Apache License 2.0 | 4 votes |
// eslint-disable-next-line complexity
function Transfer({
className = '',
onClose,
onTxSuccess,
recipientId: propRecipientId,
senderId: propSenderId,
}: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const { multisigAccount } = useMultisig();
const [amount, setAmount] = useState<BN | undefined>(BN_ZERO);
const [hasAvailable] = useState(true);
const [isProtected, setIsProtected] = useState(true);
const [isAll, setIsAll] = useState(false);
const [[maxTransfer, noFees], setMaxTransfer] = useState<[BN | null, boolean]>([null, false]);
const [recipientId, setRecipientId] = useState<string | null>(null);
const [senderId, setSenderId] = useState<string | null>(null);
const [[, recipientPhish], setPhishing] = useState<[string | null, string | null]>([null, null]);
const balances = useCall<DeriveBalancesAll>(api.derive.balances?.all, [propSenderId || senderId]);
const accountInfo = useCall<AccountInfoWithProviders | AccountInfoWithRefCount>(api.query.system.account, [
propSenderId || senderId,
]);
const [multisigExtrinsic, setMultisigExtrinsic] = useState<SubmittableExtrinsic<'promise'> | null>(null);
const [accountId, setAccountId] = useState<string | null>(null);
const isExtensionAccount = useIsInjected();
const [reserveAmount, setReserveAmount] = useState(0);
const options = useMemo<KeyringSectionOption[]>(
() =>
((multisigAccount?.meta?.addressPair as AddressPair[]) ?? []).map(({ address, ...others }) => ({
...others,
value: address,
key: address,
})),
[multisigAccount?.meta]
);
const [optionsAll, setOptionsAll] = useState<Record<string, Option[]>>({
account: [],
all: [],
});
const [depositBase, depositFactor] = useMemo(() => {
return [Number(api?.consts.multisig.depositBase.toJSON()), Number(api?.consts.multisig.depositFactor.toJSON())];
}, [api]);
const [chainDecimal, chainToken] = useMemo(() => {
return [api?.registry.chainDecimals[0], api?.registry.chainTokens[0]];
}, [api]);
const createMultiItem = useCallback(
(option: Option): Option[] => {
if (option.value === multisigAccount?.address) {
return options.map((opt) => createItem(opt));
}
return [];
},
[multisigAccount?.address, options]
);
useEffect(() => {
const subscription = keyring.keyringOption.optionsSubject.subscribe((all) => {
const optAll = Object.entries(all).reduce(
(
result: Record<string, (Option | React.ReactNode)[]>,
[type, value]
): Record<string, (Option | React.ReactNode)[]> => {
result[type] = flatten(
value.map((option): Option | React.ReactNode =>
option.value === null
? createHeader(option)
: createMultiItem(option as Option).filter((item) => isExtensionAccount(item.value))
)
);
return result;
},
{}
);
setOptionsAll(optAll as Record<string, Option[]>);
});
return () => subscription.unsubscribe();
}, [createMultiItem, isExtensionAccount]);
// eslint-disable-next-line complexity
useEffect((): void => {
const fromId = propSenderId || (senderId as string);
const toId = propRecipientId || (recipientId as string);
if (balances && balances.accountId?.eq(fromId) && fromId && toId && isFunction(api.rpc.payment?.queryInfo)) {
setTimeout((): void => {
try {
api.tx.balances
?.transfer(toId, balances.availableBalance)
.paymentInfo(fromId)
.then(({ partialFee }): void => {
// eslint-disable-next-line no-magic-numbers
const adjFee = partialFee.muln(110).div(BN_HUNDRED);
const tempMaxTransfer = balances.availableBalance.sub(adjFee);
setMaxTransfer(
tempMaxTransfer.gt(api.consts.balances?.existentialDeposit as unknown as BN)
? [tempMaxTransfer, false]
: [null, true]
);
})
.catch(console.error);
} catch (error) {
console.error((error as Error).message);
}
}, 0);
} else {
setMaxTransfer([null, false]);
}
}, [api, balances, propRecipientId, propSenderId, recipientId, senderId]);
useEffect((): void => {
checkPhishing(propSenderId || senderId, propRecipientId || recipientId)
.then(setPhishing)
.catch(console.error);
}, [propRecipientId, propSenderId, recipientId, senderId]);
const noReference = accountInfo
? isRefcount(accountInfo)
? accountInfo.refcount.isZero()
: accountInfo.consumers.isZero()
: true;
const canToggleAll =
!isProtected && balances && balances.accountId?.eq(propSenderId || senderId) && maxTransfer && noReference;
useEffect(() => {
// eslint-disable-next-line complexity
(async () => {
const fn =
canToggleAll && isAll && isFunction(api.tx.balances?.transferAll)
? api.tx.balances?.transferAll
: isProtected
? api.tx.balances?.transferKeepAlive
: api.tx.balances?.transfer;
if (!fn || !propSenderId) {
setMultisigExtrinsic(null);
return;
}
const params =
canToggleAll && isAll && isFunction(api.tx.balances?.transferAll)
? [{ Id: recipientId }, amount]
: isProtected
? [{ Id: recipientId }, amount]
: [{ Id: recipientId }, amount];
const ext = fn(...params);
// eslint-disable-next-line no-console
// console.log('amount', amount?.toString());
const ARG_LENGTH = 6;
const info = await api?.query.multisig.multisigs(propSenderId, ext?.method.hash);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const timepoint = (info as any).isSome ? (info as any)?.unwrap().when : null;
const { threshold, who } = extractExternal(propSenderId);
const others: string[] = who.filter((item) => item !== accountId);
const { weight } = (await ext?.paymentInfo(propSenderId)) || { weight: 0 };
const module = api?.tx.multisig;
const argsLength = module?.asMulti.meta.args.length || 0;
const generalParams = [threshold, others, timepoint];
const args =
argsLength === ARG_LENGTH ? [...generalParams, ext.method.toHex(), true, weight] : [...generalParams, ext];
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const multiTx = module?.asMulti(...args);
// eslint-disable-next-line no-console
// console.log('hexCallData', ext.method.toHex());
setMultisigExtrinsic(multiTx);
// Estimate reserve amount
try {
if (chainDecimal) {
setReserveAmount(
// eslint-disable-next-line no-magic-numbers
(depositBase * 2 + depositFactor * threshold + (depositFactor * (ext.method.toHex().length + 31)) / 32) /
Math.pow(10, chainDecimal)
);
}
} catch (err) {
setReserveAmount(0);
}
})();
}, [
canToggleAll,
isAll,
api,
isProtected,
amount,
recipientId,
propSenderId,
accountId,
chainDecimal,
depositBase,
depositFactor,
]);
return (
<Modal className="app--accounts-Modal" header={t<string>('Send funds')} onClose={onClose} size="large">
<Modal.Content>
<div className={className}>
<Modal.Columns
hint={t<string>('The transferred balance will be subtracted (along with fees) from the sender account.')}
>
<PureInputAddress
label={t<string>('using the selected account')}
labelExtra={<BalanceFree label={<label>{t<string>('free balance')}</label>} params={accountId} />}
onChange={setAccountId}
optionsAll={optionsAll}
type="account"
/>
</Modal.Columns>
<Modal.Columns
hint={t<string>('The transferred balance will be subtracted (along with fees) from the sender account.')}
>
<InputAddress
defaultValue={propSenderId}
help={t<string>('The account you will send funds from.')}
isDisabled={!!propSenderId}
label={t<string>('send from account')}
labelExtra={<Available label={t<string>('transferrable')} params={propSenderId || senderId} />}
onChange={setSenderId}
type="account"
/>
</Modal.Columns>
<Modal.Columns
hint={t<string>(
'The beneficiary will have access to the transferred fees when the transaction is included in a block.'
)}
>
<InputAddress
defaultValue={propRecipientId}
help={t<string>('Select a contact or paste the address you want to send funds to.')}
isDisabled={!!propRecipientId}
label={t<string>('send to address')}
labelExtra={<Available label={t<string>('transferrable')} params={propRecipientId || recipientId} />}
onChange={setRecipientId}
type="allPlus"
/>
{recipientPhish && (
<MarkError
content={t<string>('The recipient is associated with a known phishing site on {{url}}', {
replace: { url: recipientPhish },
})}
/>
)}
</Modal.Columns>
<Modal.Columns
hint={t<string>(
'If the recipient account is new, the balance needs to be more than the existential deposit. Likewise if the sending account balance drops below the same value, the account will be removed from the state.'
)}
>
{canToggleAll && isAll ? (
<InputBalance
autoFocus
defaultValue={maxTransfer}
help={t<string>('The full account balance to be transferred, minus the transaction fees')}
isDisabled
key={maxTransfer?.toString()}
label={t<string>('transferrable minus fees')}
/>
) : (
<>
<InputBalance
autoFocus
help={t<string>(
'Type the amount you want to transfer. Note that you can select the unit on the right e.g sending 1 milli is equivalent to sending 0.001.'
)}
isError={!hasAvailable}
isZeroable
label={t<string>('amount')}
maxValue={maxTransfer}
onChange={setAmount}
/>
<InputBalance
defaultValue={api.consts.balances?.existentialDeposit}
help={t<string>('The minimum amount that an account should have to be deemed active')}
isDisabled
label={t<string>('existential deposit')}
/>
</>
)}
</Modal.Columns>
<Modal.Columns
hint={t('With the keep-alive option set, the account is protected against removal due to low balances.')}
>
{isFunction(api.tx.balances?.transferKeepAlive) && (
<Toggle
className="typeToggle"
label={
isProtected
? t<string>('Transfer with account keep-alive checks')
: t<string>('Normal transfer without keep-alive checks')
}
onChange={setIsProtected}
value={isProtected}
/>
)}
{canToggleAll && (
<Toggle
className="typeToggle"
label={t<string>('Transfer the full account balance, reap the sender')}
onChange={setIsAll}
value={isAll}
/>
)}
{!isProtected && !noReference && (
<MarkWarning
content={t<string>(
'There is an existing reference count on the sender account. As such the account cannot be reaped from the state.'
)}
/>
)}
{noFees && (
<MarkWarning
content={t<string>(
'The transaction, after application of the transfer fees, will drop the available balance below the existential deposit. As such the transfer will fail. The account needs more free funds to cover the transaction fees.'
)}
/>
)}
</Modal.Columns>
</div>
</Modal.Content>
<div className="flex items-center justify-between px-5">
<Text style={{ color: 'rgba(78,78,78,0.6)', marginLeft: '20px' }}>
{t('multisig.estimate_reserve')} {reserveAmount} {chainToken}
</Text>
<Modal.Actions onCancel={onClose}>
<TxButton
// accountId={propSenderId || senderId}
accountId={accountId}
icon="paper-plane"
isDisabled={!hasAvailable || !(propRecipientId || recipientId) || !amount || !!recipientPhish}
label={t<string>('Make Transfer')}
onStart={onClose}
extrinsic={multisigExtrinsic}
onSuccess={onTxSuccess}
// params={
// canToggleAll && isAll
// ? isFunction(api.tx.balances?.transferAll)
// ? [propRecipientId || recipientId, false]
// : [propRecipientId || recipientId, maxTransfer]
// : [propRecipientId || recipientId, amount]
// }
// tx={
// canToggleAll && isAll && isFunction(api.tx.balances?.transferAll)
// ? api.tx.balances?.transferAll
// : isProtected
// ? api.tx.balances?.transferKeepAlive
// : api.tx.balances?.transfer
// }
/>
</Modal.Actions>
</div>
</Modal>
);
}