@polkadot/types/interfaces#Call TypeScript Examples
The following examples show how to use
@polkadot/types/interfaces#Call.
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: useWeight.ts From crust-apps with Apache License 2.0 | 6 votes |
// for a given call, calculate the weight
export function useWeight (call?: Call | null): [BN, number] {
const { api } = useApi();
const mountedRef = useIsMountedRef();
const [state, setState] = useState(EMPTY_STATE);
useEffect((): void => {
if (call) {
api.tx(call)
.paymentInfo(ZERO_ACCOUNT)
.then(({ weight }) => mountedRef.current && setState([weight, call.encodedLength]))
.catch(console.error);
} else {
setState(EMPTY_STATE);
}
}, [api, call, mountedRef]);
return state;
}
Example #2
Source File: Address.tsx From crust-apps with Apache License 2.0 | 6 votes |
function findCall (tx: Call | SubmittableExtrinsic<'promise'>): { method: string; section: string } {
try {
const { method, section } = tx.registry.findMetaCall(tx.callIndex);
return { method, section };
} catch (error) {
return { method: 'unknown', section: 'unknown' };
}
}
Example #3
Source File: Address.tsx From crust-apps with Apache License 2.0 | 6 votes |
function filterProxies (allAccounts: string[], tx: Call | SubmittableExtrinsic<'promise'>, proxies: [string, ProxyType][]): string[] {
// check an array of calls to all have proxies as the address
const checkCalls = (address: string, txs: Call[]): boolean =>
!txs.some((tx) => !filterProxies(allAccounts, tx, proxies).includes(address));
// get the call info
const { method, section } = findCall(tx);
return proxies
.filter(([address, proxy]): boolean => {
if (!allAccounts.includes(address)) {
return false;
}
switch (proxy.toString()) {
case 'Any':
return true;
case 'Governance':
return ['council', 'democracy', 'elections', 'electionsPhragmen', 'poll', 'society', 'technicalCommittee', 'tips', 'treasury'].includes(section);
case 'IdentityJudgement':
return section === 'identity' && method === 'provideJudgement';
case 'NonTransfer':
return !(section === 'balances' || (section === 'indices' && method === 'transfer') || (section === 'vesting' && method === 'vestedTransfer'));
case 'Staking':
return section === 'staking' ||
(section === 'utility' && (
(method === 'batch' && checkCalls(address, tx.args[0] as Vec<Call>)) ||
(method === 'asLimitedSub' && checkCalls(address, [tx.args[0] as Call]))
));
case 'SudoBalances':
return (section === 'sudo' && (method === 'sudo' && findCall(tx.args[0] as Call).section === 'balances')) ||
(section === 'utility' && (method === 'batch' && checkCalls(address, tx.args[0] as Vec<Call>)));
default:
return false;
}
})
.map(([address]) => address);
}
Example #4
Source File: multisig.ts From subscan-multisig-react with Apache License 2.0 | 6 votes |
txMethodDescription = (
data: Call | undefined | null,
api: ApiPromise | null
): { name: string; type: string; value: string }[] => {
if (!data || !api) {
return [];
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const call = data.toHuman() as any;
if (call) {
const meta = api.tx[call.section][call.method].meta.toJSON();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const callJson = data.toJSON() as any;
const params = meta.args as { name: string; type: string }[];
return params.map(({ name, type }) => {
const value = callJson.args[name];
return {
name,
type,
value: typeof value === 'object' ? Object.values(value).join(' ') : value,
};
});
}
return [];
}
Example #5
Source File: multisig.ts From subscan-multisig-react with Apache License 2.0 | 6 votes |
txMethod = (data: Call | undefined | null, api: ApiPromise | null): string => {
if (!data || !api) {
return '-';
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const call = data?.toHuman() as any;
if (call) {
const meta = api.tx[call.section][call.method].meta.toJSON();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return `${call.section}.${call.method}(${(meta.args as any[]).map((item) => item.name).join(',')})`;
}
return '-';
}
Example #6
Source File: collective.ts From commonwealth with GNU General Public License v3.0 | 6 votes |
public createTx(
author: SubstrateAccount,
threshold: number,
action: Call,
length?: number,
fromTechnicalCommittee?: boolean,
) {
// TODO: check council status
const title = this._Chain.methodToTitle(action);
// handle differing versions of substrate API
const txFunc = fromTechnicalCommittee
? ((api: ApiPromise) => api.tx.technicalCommittee.propose.meta.args.length === 3
? api.tx.technicalCommittee.propose(threshold, action, length)
: (api.tx.technicalCommittee.propose as any)(threshold, action))
: ((api: ApiPromise) => api.tx.council.propose.meta.args.length === 3
? api.tx.council.propose(threshold, action, length)
: (api.tx.council.propose as any)(threshold, action, null));
return this._Chain.createTXModalData(
author,
txFunc,
'createCouncilMotion',
title
);
}
Example #7
Source File: Address.tsx From subscan-multisig-react with Apache License 2.0 | 6 votes |
function findCall(tx: Call | SubmittableExtrinsic<'promise'>): { method: string; section: string } {
try {
const { method, section } = tx.registry.findMetaCall(tx.callIndex);
return { method, section };
} catch (error) {
return { method: 'unknown', section: 'unknown' };
}
}
Example #8
Source File: democracy_proposals.ts From commonwealth with GNU General Public License v3.0 | 6 votes |
public notePreimage(author: SubstrateAccount, action: Call, encodedProposal: string) {
const title = this._Chain.methodToTitle(action);
return this._Chain.createTXModalData(
author,
(api: ApiPromise) => api.tx.democracy.notePreimage(encodedProposal),
'notePreimage',
title
);
}
Example #9
Source File: democracy_proposals.ts From commonwealth with GNU General Public License v3.0 | 6 votes |
public noteImminentPreimage(author: SubstrateAccount, action: Call, encodedProposal: string) {
const title = this._Chain.methodToTitle(action);
return this._Chain.createTXModalData(
author,
(api: ApiPromise) => api.tx.democracy.notePreimage(encodedProposal),
'noteImminentPreimage',
title,
);
}
Example #10
Source File: democracy_referendum.ts From commonwealth with GNU General Public License v3.0 | 6 votes |
// public async proxyVoteTx(vote: BinaryVote<SubstrateCoin>) {
// const proxyFor = await (vote.account as SubstrateAccount).proxyFor.pipe(first()).toPromise();
// if (!proxyFor) {
// throw new Error('not a proxy');
// }
// const srmlVote = this._Chain.createType('Vote', {
// aye: vote.choice,
// conviction: convictionToSubstrate(this._Chain, weightToConviction(vote.weight)),
// });
// return this._Chain.createTXModalData(
// vote.account as SubstrateAccount,
// (api: ApiPromise) => api.tx.democracy.proxyVote(this.data.index, srmlVote),
// 'submitProxyDemocracyVote',
// this.title
// );
// }
public async notePreimage(author: SubstrateAccount, action: Call) {
const txFunc = (api: ApiPromise) => api.tx.democracy.notePreimage(action.toHex());
return this._Chain.createTXModalData(
author,
txFunc,
'notePreimage',
this._Chain.methodToTitle(action),
);
}
Example #11
Source File: useWeight.ts From subscan-multisig-react with Apache License 2.0 | 6 votes |
// for a given call, calculate the weight
export function useWeight(call?: Call | null): [BN, number] {
const { api } = useApi();
const mountedRef = useIsMountedRef();
const [state, setState] = useState(EMPTY_STATE);
useEffect((): void => {
if (call && isFunction(api.rpc.payment?.queryInfo)) {
api
.tx(call)
.paymentInfo(ZERO_ACCOUNT)
.then(({ weight }) => mountedRef.current && setState([weight, call.encodedLength]))
.catch(console.error);
} else {
setState(EMPTY_STATE);
}
}, [api, call, mountedRef]);
return state;
}
Example #12
Source File: types.ts From commonwealth with GNU General Public License v3.0 | 6 votes |
export function formatCall(c: Call | { section: string, method: string, args: string[] }): string {
// build args string
const args: (string | Codec)[] = c.args;
const argsStr = args.map((v: Codec | string): string => {
if (!v) return '[unknown]';
const vStr = v.toString();
if (vStr.length < 16) return vStr;
return `${vStr.slice(0, 15)}…`;
}).join(', ');
// finish format
return `${c.section}.${c.method}(${argsStr})`;
}
Example #13
Source File: multisig.ts From subscan-multisig-react with Apache License 2.0 | 5 votes |
txDoc = (data: Call | undefined | null): string => {
if (!data) {
return '-';
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (data?.meta as any).get('documentation').toHuman().join('');
}
Example #14
Source File: Address.tsx From subscan-multisig-react with Apache License 2.0 | 5 votes |
function filterProxies(
allAccounts: string[],
tx: Call | SubmittableExtrinsic<'promise'>,
proxies: [string, ProxyType][]
): string[] {
// check an array of calls to all have proxies as the address
const checkCalls = (address: string, txs: Call[]): boolean =>
!txs.some((tx) => !filterProxies(allAccounts, tx, proxies).includes(address));
// get the call info
const { method, section } = findCall(tx);
return proxies
.filter(([address, proxy]): boolean => {
if (!allAccounts.includes(address)) {
return false;
}
switch (proxy.toString()) {
case 'Any':
return true;
case 'Governance':
return [
'council',
'democracy',
'elections',
'electionsPhragmen',
'phragmenElection',
'poll',
'society',
'technicalCommittee',
'tips',
'treasury',
].includes(section);
case 'IdentityJudgement':
return section === 'identity' && method === 'provideJudgement';
case 'NonTransfer':
return !(
section === 'balances' ||
(section === 'indices' && method === 'transfer') ||
(section === 'vesting' && method === 'vestedTransfer')
);
case 'Staking':
return (
section === 'staking' ||
(section === 'utility' &&
((method === 'batch' && checkCalls(address, tx.args[0] as Vec<Call>)) ||
(method === 'asLimitedSub' && checkCalls(address, [tx.args[0] as Call]))))
);
case 'SudoBalances':
return (
(section === 'sudo' && method === 'sudo' && findCall(tx.args[0] as Call).section === 'balances') ||
(section === 'utility' && method === 'batch' && checkCalls(address, tx.args[0] as Vec<Call>))
);
default:
return false;
}
})
.map(([address]) => address);
}
Example #15
Source File: shared.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
public getTxMethod(mod: string, func: string, args: any[]): Call {
const result = this.api.tx[mod][func];
if (!result) {
throw new Error(`unsupported transaction: ${mod}::${func}`);
}
return this.api.findCall(result.callIndex)(...args);
}
Example #16
Source File: identities.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
// requires ForceOrigin or Root!
public killIdentityMethod(target: SubstrateIdentity): Call {
if (!target.exists) {
throw new Error('target identity does not exist');
}
const func = this._Chain.getTxMethod('identity', 'killIdentity', [ target.account.address ]);
return func;
}
Example #17
Source File: identities.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
// requires RegistrarOrigin or Root!
public addRegistrarMethod(account: SubstrateAccount): Call {
const func = this._Chain.getTxMethod('identity', 'addRegistrar', [ account.address ]);
return func;
}
Example #18
Source File: democracy_referendum.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
public noteImminentPreimage(author: SubstrateAccount, action: Call) {
return this._Chain.createTXModalData(
author,
(api: ApiPromise) => api.tx.democracy.noteImminentPreimage(action.toHex()),
'noteImminentPreimage',
this._Chain.methodToTitle(action),
);
}
Example #19
Source File: democracy_proposals.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
public async createTx(author: SubstrateAccount, action: Call, proposalHash: Hash, deposit: SubstrateCoin) {
const txFunc = (api: ApiPromise) => api.tx.democracy.propose(proposalHash, deposit.asBN);
const title = this._Chain.methodToTitle(action);
return this._Chain.createTXModalData(author, txFunc, 'createDemocracyProposal', title);
}
Example #20
Source File: collective.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
public createExternalProposalDefault(author: SubstrateAccount, threshold: number, action: Call, length) {
// only on kusama
const func = this._Chain.getTxMethod('democracy', 'externalProposeDefault', [ action.hash ]);
return this.createTx(author, threshold, func, length);
}
Example #21
Source File: collective.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
public createExternalProposalMajority(author: SubstrateAccount, threshold: number, action: Call, length) {
const func = this._Chain.getTxMethod('democracy', 'externalProposeMajority', [ action.hash ]);
return this.createTx(author, threshold, func, length);
}
Example #22
Source File: collective.ts From commonwealth with GNU General Public License v3.0 | 5 votes |
public createExternalProposal(author: SubstrateAccount, threshold: number, action: Call, length: number) {
const func = this._Chain.getTxMethod('democracy', 'externalPropose', [ action.hash ]);
return this.createTx(author, threshold, func, length);
}
Example #23
Source File: TxApprove.tsx From subscan-multisig-react with Apache License 2.0 | 4 votes |
// eslint-disable-next-line complexity
export function TxApprove({ entry, txSpy, onOperation }: TxOperationComponentProps) {
const { t } = useTranslation();
const { accounts, api } = useApi();
const [getApproveTx] = useMultiApprove();
const { queueExtrinsic } = useContext(StatusContext);
const [getUnapprovedInjectedList] = useUnapprovedAccounts();
const { setIsPageLock, queryInProgress, refreshConfirmedAccount } = useMultisigContext();
const unapprovedAddresses = getUnapprovedInjectedList(entry);
const availableAccounts = (accounts ?? []).filter((extAddr) => unapprovedAddresses.includes(extAddr.address));
const [inputCallDataModalVisible, setInputCallDataModalVisible] = useState(false);
const handleApprove = useCallback(
(accountId: string, target: Entry) => {
setIsPageLock(true);
setInputCallDataModalVisible(false);
getApproveTx(target, accountId).then((tx) => {
const queueTx: PartialQueueTxExtrinsic = {
extrinsic: tx,
accountId,
txSuccessCb: () => {
makeSure(txSpy)(null);
queryInProgress();
setTimeout(() => {
refreshConfirmedAccount();
// eslint-disable-next-line no-magic-numbers
}, 6000);
},
};
queueExtrinsic(queueTx);
setIsPageLock(false);
makeSure(txSpy)(queueTx);
});
makeSure(onOperation)({
entry: target,
type: 'approve',
accounts: availableAccounts.map((account) => account.address),
});
},
[
availableAccounts,
getApproveTx,
onOperation,
queryInProgress,
queueExtrinsic,
refreshConfirmedAccount,
setIsPageLock,
txSpy,
]
);
if (!entry.callHash || !entry.callData) {
return (
<>
<Button onClick={() => setInputCallDataModalVisible(true)}>{t('approve')}</Button>
<InputCallDataModal
visible={inputCallDataModalVisible}
onCancel={() => setInputCallDataModalVisible(false)}
availableAccounts={availableAccounts}
callHash={entry.callHash || ''}
onConfirm={(selectedAddress, callData) => {
try {
const callDataObj = api?.registry.createType('Call', callData) as Call;
handleApprove(selectedAddress, { ...entry, callHash: entry.callHash, callData: callDataObj });
} catch {
message.error(t('decode call data error'));
}
}}
/>
</>
);
} else if (availableAccounts.length === 1) {
return <Button onClick={() => handleApprove(availableAccounts[0].address, entry)}>{t('approve')}</Button>;
} else {
return (
<Popover
content={
<Radio.Group
onChange={(event) => {
handleApprove(event.target.value, entry);
}}
value={null}
>
<Space direction="vertical">
{availableAccounts.map((acc) => (
<Radio.Button
value={acc.address}
key={acc.address}
className="max-w-xs md:max-w-full overflow-hidden overflow-ellipsis whitespace-nowrap"
>
{acc.meta.name} - {acc.address}
</Radio.Button>
))}
</Space>
</Radio.Group>
}
title={t('Select approve account')}
trigger="focus"
>
<Button>{t('approve')}</Button>
</Popover>
);
}
}
Example #24
Source File: MultisigApprove.tsx From crust-apps with Apache License 2.0 | 4 votes |
function MultisigApprove ({ className = '', onClose, ongoing, threshold, who }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const { allAccounts } = useAccounts();
const [callData, setCallData] = useState<Call | null>(null);
const [callWeight] = useWeight(callData);
const [hash, setHash] = useState<string | null>(ongoing[0][0].toHex());
const [{ isMultiCall, multisig }, setMultisig] = useState<MultiInfo>({ isMultiCall: false, multisig: null });
const [isCallOverride, setCallOverride] = useState(true);
const [others, setOthers] = useState<AccountId[]>([]);
const [signatory, setSignatory] = useState<string | null>(null);
const [whoFilter, setWhoFilter] = useState<string[]>([]);
const [type, setType] = useState<string | null>('aye');
const [tx, setTx] = useState<SubmittableExtrinsic<'promise'> | null>(null);
const calltypes = useMemo<Option[]>(
() => [
{ text: t<string>('Approve this call hash'), value: 'aye' },
{ text: t<string>('Cancel this call hash'), value: 'nay' }
],
[t]
);
const hashes = useMemo<Option[]>(
() => ongoing.map(([h]) => ({ text: h.toHex(), value: h.toHex() })),
[ongoing]
);
// filter the current multisig by supplied hash
useEffect((): void => {
const [, multisig] = ongoing.find(([h]) => h.eq(hash)) || [null, null];
setMultisig({
isMultiCall: !!multisig && (multisig.approvals.length + 1) >= threshold,
multisig
});
setCallData(null);
}, [hash, ongoing, threshold]);
// the others are all the who elements, without the current signatory (re-encoded)
useEffect((): void => {
setOthers(
who
.map((w) => api.createType('AccountId', w))
.filter((w) => !w.eq(signatory))
);
}, [api, signatory, who]);
// Filter the who by those not approved yet that is an actual account we own. In the case of
// rejections, we defer to the the first approver, since he is the only one to send the cancel
// On reaching threshold, we include all possible signatories in the list
useEffect((): void => {
const hasThreshold = multisig && (multisig.approvals.length >= threshold);
setWhoFilter(
who
.map((w) => api.createType('AccountId', w).toString())
.filter((w) => allAccounts.some((a) => a === w) && multisig && (
type === 'nay'
? multisig.approvals[0].eq(w)
: hasThreshold || !multisig.approvals.some((a) => a.eq(w))
))
);
}, [api, allAccounts, multisig, threshold, type, who]);
// based on the type, multisig, others create the tx. This can be either an approval or final call
useEffect((): void => {
const multiMod = api.tx.multisig || api.tx.utility;
setTx(() =>
hash && multisig
? type === 'aye'
? isMultiCall && isCallOverride
? callData
? multiMod.asMulti.meta.args.length === 6
? multiMod.asMulti(threshold, others, multisig.when, callData.toHex(), false, callWeight)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore (We are doing toHex here since we have a Vec<u8> input)
: multiMod.asMulti(threshold, others, multisig.when, callData)
: null
: multiMod.approveAsMulti.meta.args.length === 5
? multiMod.approveAsMulti(threshold, others, multisig.when, hash, callWeight)
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
: multiMod.approveAsMulti(threshold, others, multisig.when, hash)
: multiMod.cancelAsMulti(threshold, others, multisig.when, hash)
: null
);
}, [api, callData, callWeight, hash, isCallOverride, isMultiCall, others, multisig, threshold, type]);
// when the actual call input changes, create a call and set it
const _setCallData = useCallback(
(callHex: string): void => {
try {
assert(isHex(callHex), 'Hex call data required');
const callData = api.createType('Call', callHex);
setCallData(
callData.hash.eq(hash)
? callData
: null
);
} catch (error) {
setCallData(null);
}
},
[api, hash]
);
const isAye = type === 'aye';
return (
<Modal
className={className}
header={t<string>('Pending call hashes')}
size='large'
>
<Modal.Content>
<Modal.Columns hint={t('The call hash from the list of available and unapproved calls.')}>
<Dropdown
help={t<string>('The call hashes that have not been executed as of yet.')}
label={t<string>('pending hashes')}
onChange={setHash}
options={hashes}
value={hash}
/>
</Modal.Columns>
<Modal.Columns hint={t('The operation type to apply. For approvals both non-final and final approvals are supported.')}>
<Dropdown
help={t<string>('Either approve or reject this call.')}
label={t<string>('approval type')}
onChange={setType}
options={calltypes}
value={type}
/>
</Modal.Columns>
{whoFilter.length !== 0 && (
<>
<Modal.Columns hint={t('For approvals outstanding approvers will be shown, for hashes that should be cancelled the first approver is required.')}>
<InputAddress
filter={whoFilter}
help={t<string>('The signatory to send the approval/cancel from')}
label={t<string>('signatory')}
onChange={setSignatory}
/>
</Modal.Columns>
{type === 'aye' && isMultiCall && (
<>
{isCallOverride && (
<Modal.Columns hint={t('The call data for this transaction matching the hash. Once sent, the multisig will be executed against this.')}>
<Input
autoFocus
help={t('For final approvals, the actual full call data is required to execute the transaction')}
isError={!callData}
label={t('call data for final approval')}
onChange={_setCallData}
/>
</Modal.Columns>
)}
<Modal.Columns hint={t('Swap to a non-executing approval type, with subsequent calls providing the actual call data.')}>
<Toggle
className='tipToggle'
label={
isMultiCall
? t<string>('Multisig message with call (for final approval)')
: t<string>('Multisig approval with hash (non-final approval)')
}
onChange={setCallOverride}
value={isCallOverride}
/>
</Modal.Columns>
</>
)}
</>
)}
</Modal.Content>
<Modal.Actions onCancel={onClose}>
<TxButton
accountId={signatory}
extrinsic={tx}
icon={isAye ? 'check' : 'times'}
isDisabled={!tx || (isAye && !whoFilter.length)}
label={isAye ? 'Approve' : 'Reject'}
onStart={onClose}
/>
</Modal.Actions>
</Modal>
);
}