From 3bcf704b53f3c11d6fb2ec2a0c1635299fc530f4 Mon Sep 17 00:00:00 2001 From: Thibaut Sardan Date: Tue, 17 Sep 2024 21:58:57 +0100 Subject: [PATCH] deepTxs hooks compatibilityToken --- .../src/components/modals/ChangeMultisig.tsx | 122 +++++++----------- .../src/components/modals/DeepTxCreation.tsx | 73 ++++------- packages/ui/src/contexts/ApiContext.tsx | 11 +- packages/ui/src/hooks/useGetMultisigTx.tsx | 24 ++-- packages/ui/src/hooks/usePendingTx.tsx | 1 - .../src/hooks/useProxyAdditionNeededFunds.tsx | 17 +-- .../src/hooks/useWalletConnectNamespace.tsx | 18 ++- packages/ui/src/types.ts | 9 +- packages/ui/src/utils/getApproveAsMultiTx.ts | 17 ++- packages/ui/src/utils/getAsMultiTx.ts | 13 +- packages/ui/src/utils/txHash.ts | 5 + 11 files changed, 152 insertions(+), 158 deletions(-) create mode 100644 packages/ui/src/utils/txHash.ts diff --git a/packages/ui/src/components/modals/ChangeMultisig.tsx b/packages/ui/src/components/modals/ChangeMultisig.tsx index 7c16ba10..91bf162e 100644 --- a/packages/ui/src/components/modals/ChangeMultisig.tsx +++ b/packages/ui/src/components/modals/ChangeMultisig.tsx @@ -17,7 +17,6 @@ import Summary from '../../pages/Creation/Summary' import { useApi } from '../../contexts/ApiContext' import { useAccounts } from '../../contexts/AccountsContext' import { useSigningCallback } from '../../hooks/useSigningCallback' -import { useToasts } from '../../contexts/ToastContext' import { AccountBadge } from '../../types' import { getIntersection } from '../../utils' import GenericAccountSelection, { AccountBaseInfo } from '../select/GenericAccountSelection' @@ -26,12 +25,13 @@ import { useCheckBalance } from '../../hooks/useCheckBalance' import { formatBnBalance } from '../../utils/formatBnBalance' import { useMultisigProposalNeededFunds } from '../../hooks/useMultisigProposalNeededFunds' import { MdErrorOutline as ErrorOutlineIcon } from 'react-icons/md' -import { useGetSubscanLinks } from '../../hooks/useSubscanLink' import { Button } from '../library' import { ModalCloseButton } from '../library/ModalCloseButton' import { useGetSortAddress } from '../../hooks/useGetSortAddress' import { useGetMultisigAddress } from '../../contexts/useGetMultisigAddress' import { getAsMultiTx } from '../../utils/getAsMultiTx' +import { TypedApi } from 'polkadot-api' +import { dot, MultiAddress, ProxyType } from '@polkadot-api/descriptors' interface Props { onClose: () => void @@ -41,14 +41,15 @@ interface Props { type Step = 'selection' | 'summary' | 'call1' | 'call2' const ChangeMultisig = ({ onClose, className }: Props) => { - const { getSubscanExtrinsicLink } = useGetSubscanLinks() const modalRef = useRef(null) - const { api, chainInfo } = useApi() + const { api, chainInfo, compatibilityToken } = useApi() const { selectedMultiProxy, getMultisigAsAccountBaseInfo, getMultisigByAddress } = useMultiProxy() - const { addToast } = useToasts() const signCallBack2 = useSigningCallback({ onSuccess: onClose, - onError: onClose + onError: (e) => { + onClose() + onErrorCallback(e) + } }) const { getSortAddress } = useGetSortAddress() const { selectedAccount, selectedSigner, ownAddressList } = useAccounts() @@ -85,8 +86,8 @@ const ChangeMultisig = ({ onClose, className }: Props) => { const multisigList = useMemo(() => getMultisigAsAccountBaseInfo(), [getMultisigAsAccountBaseInfo]) const [callError, setCallError] = useState('') - const firstCall = useMemo(() => { - if (!api) { + const secondCall = useMemo(() => { + if (!api || !compatibilityToken) { // console.error('api is not ready') return } @@ -119,29 +120,40 @@ const ChangeMultisig = ({ onClose, className }: Props) => { selectedMultisig.signatories.filter((sig) => sig !== selectedAccount.address) ) - const addProxyTx = api.tx.proxy.addProxy(newMultisigAddress, 'Any', 0) - const proxyTx = api.tx.proxy.proxy(selectedMultiProxy?.proxy, null, addProxyTx) - // call with the old multisig + const addProxyTx = (api as TypedApi).tx.Proxy.add_proxy({ + delegate: MultiAddress.Id(newMultisigAddress), + proxy_type: ProxyType.Any(), + delay: 0 + }) + + const proxyTx = (api as TypedApi).tx.Proxy.proxy({ + real: MultiAddress.Id(selectedMultiProxy?.proxy), + force_proxy_type: undefined, + call: addProxyTx.decodedCall + }) + // call with the old multisig to delete the new one return getAsMultiTx({ api, threshold: oldThreshold, otherSignatories: otherOldSignatories, - tx: proxyTx + tx: proxyTx, + compatibilityToken }) }, [ api, chainInfo, + compatibilityToken, getSortAddress, newMultisigAddress, newThreshold, oldThreshold, selectedAccount, - selectedMultiProxy, + selectedMultiProxy?.proxy, selectedMultisig ]) - const secondCall = useMemo(() => { - if (!api) { + const firstCall = useMemo(() => { + if (!api || !compatibilityToken) { // console.error('api is not ready') return } @@ -169,13 +181,23 @@ const ChangeMultisig = ({ onClose, className }: Props) => { const otherNewSignatories = getSortAddress( newSignatories.filter((sig) => sig !== selectedAccount.address) ) - const removeProxyTx = api.tx.proxy.removeProxy(selectedMultisig?.address, 'Any', 0) - const proxyTx = api.tx.proxy.proxy(selectedMultiProxy?.proxy, null, removeProxyTx) + const removeProxyTx = (api as TypedApi).tx.Proxy.remove_proxy({ + delegate: MultiAddress.Id(selectedMultisig?.address), + proxy_type: ProxyType.Any(), + delay: 0 + }) + const proxyTx = (api as TypedApi).tx.Proxy.proxy({ + real: MultiAddress.Id(selectedMultiProxy?.proxy), + force_proxy_type: undefined, + call: removeProxyTx.decodedCall + }) + return getAsMultiTx({ api, otherSignatories: otherNewSignatories, threshold: newThreshold, - tx: proxyTx + tx: proxyTx, + compatibilityToken }) }, [ api, @@ -185,7 +207,8 @@ const ChangeMultisig = ({ onClose, className }: Props) => { newThreshold, selectedAccount, selectedMultiProxy, - selectedMultisig + selectedMultisig, + compatibilityToken ]) const { multisigProposalNeededFunds: firstCallNeededFunds, reserved: firstCallReserved } = @@ -201,7 +224,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => { threshold: newThreshold }) const neededBalance = useMemo( - () => firstCallNeededFunds.add(secondCallNeededFunds), + () => firstCallNeededFunds + secondCallNeededFunds, [firstCallNeededFunds, secondCallNeededFunds] ) const { hasEnoughFreeBalance: hasSignerEnoughFunds } = useCheckBalance({ @@ -260,37 +283,14 @@ const ChangeMultisig = ({ onClose, className }: Props) => { return } - if (!secondCall) { + if (!secondCall || !selectedSigner) { return } setCurrentStep('call2') - secondCall - .signAndSend( - selectedAccount.address, - { signer: selectedSigner, withSignedTransaction: true }, - signCallBack2 - ) - .catch((error: Error) => { - addToast({ - title: error.message, - type: 'error', - link: getSubscanExtrinsicLink(secondCall.hash.toHex()) - }) - onErrorCallback(error.message) - }) - }, [ - callError, - api, - selectedAccount, - secondCall, - selectedSigner, - signCallBack2, - addToast, - getSubscanExtrinsicLink, - onErrorCallback - ]) + secondCall.signSubmitAndWatch(selectedSigner, { at: 'best' }).subscribe(signCallBack2) + }, [callError, api, selectedAccount, secondCall, selectedSigner, signCallBack2]) const signCallBack1 = useSigningCallback({ onSuccess: onMakeSecondCall, @@ -309,36 +309,14 @@ const ChangeMultisig = ({ onClose, className }: Props) => { return } - if (!firstCall) { + if (!firstCall || !selectedSigner) { return } setCurrentStep('call1') - firstCall - .signAndSend( - selectedAccount.address, - { signer: selectedSigner, withSignedTransaction: true }, - signCallBack1 - ) - .catch((error: Error) => { - addToast({ - title: error.message, - type: 'error', - link: getSubscanExtrinsicLink(firstCall.hash.toHex()) - }) - onErrorCallback(error.message) - }) - }, [ - api, - selectedAccount, - firstCall, - selectedSigner, - signCallBack1, - addToast, - getSubscanExtrinsicLink, - onErrorCallback - ]) + firstCall.signSubmitAndWatch(selectedSigner, { at: 'best' }).subscribe(signCallBack1) + }, [api, selectedAccount, firstCall, selectedSigner, signCallBack1]) const onClickNext = useCallback(() => { if (currentStep === 'summary') { @@ -437,7 +415,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => { balanceMin={neededBalance} isBalanceError={!hasSignerEnoughFunds} selectedMultisig={selectedMultisig} - reservedBalance={firstCallReserved.add(secondCallReserved)} + reservedBalance={firstCallReserved + secondCallReserved} /> )} {(currentStep === 'call1' || currentStep === 'call2') && ( diff --git a/packages/ui/src/components/modals/DeepTxCreation.tsx b/packages/ui/src/components/modals/DeepTxCreation.tsx index 00cc7016..766d76b3 100644 --- a/packages/ui/src/components/modals/DeepTxCreation.tsx +++ b/packages/ui/src/components/modals/DeepTxCreation.tsx @@ -7,9 +7,7 @@ import { useApi } from '../../contexts/ApiContext' import { MultisigAggregated, useMultiProxy } from '../../contexts/MultiProxyContext' import CallInfo from '../CallInfo' import SignerSelection from '../select/SignerSelection' -import { useToasts } from '../../contexts/ToastContext' import { useSigningCallback } from '../../hooks/useSigningCallback' -import { useGetSubscanLinks } from '../../hooks/useSubscanLink' import { useCallInfoFromCallData } from '../../hooks/useCallInfoFromCallData' import { ModalCloseButton } from '../library/ModalCloseButton' import { useCheckBalance } from '../../hooks/useCheckBalance' @@ -21,6 +19,7 @@ import { HexString } from '../../types' import { getDisplayArgs, getErrorMessageReservedFunds, getExtrinsicName } from '../../utils' import { useMultisigProposalNeededFunds } from '../../hooks/useMultisigProposalNeededFunds' import { formatBnBalance } from '../../utils/formatBnBalance' +import { hashFromTx } from '../../utils/txHash' export interface DeepTxCreationProps { onClose: () => void @@ -41,12 +40,10 @@ const DeepTxCreationModal = ({ parentMultisigInfo, currentMultisigInvolved }: DeepTxCreationProps) => { - const { getSubscanExtrinsicLink } = useGetSubscanLinks() - const { api, chainInfo } = useApi() + const { api, chainInfo, compatibilityToken } = useApi() const [isSubmitting, setIsSubmitting] = useState(false) const { selectedAccount, selectedSigner } = useAccounts() const [errorMessage, setErrorMessage] = useState('') - const { addToast } = useToasts() const { selectedMultiProxy, getMultisigByAddress, setRefetchMultisigTimeoutMinutes } = useMultiProxy() const [addedCallData, setAddedCallData] = useState() @@ -64,7 +61,7 @@ const DeepTxCreationModal = ({ // this will never be a proxy, if there's a proxy, it's already in the call const parentMultisigTx = useGetMultisigTx({ fromAddress: parentMultisigInfo.parentSignatoryAddress, - extrinsicToCall: (api && parentCallInfo?.call && api.tx(parentCallInfo?.call)) || undefined, + extrinsicToCall: (api && parentCallInfo?.call && parentCallInfo?.call) || undefined, senderAddress: parentMultisigInfo.parentSignatoryAddress, isProxy: false, threshold: parentMultisigInfo.threshold, @@ -86,7 +83,7 @@ const DeepTxCreationModal = ({ // and calls a asMulti because it's a creation const fullTx = useGetMultisigTx({ fromAddress: parentMultisigInfo.parentSignatoryAddress, - extrinsicToCall: (api && parentMultisigTx && api.tx(parentMultisigTx)) || undefined, + extrinsicToCall: (api && parentMultisigTx && parentMultisigTx) || undefined, senderAddress: selectedAccount?.address, isProxy: !!parentMultisigInfo.isSignatoryProxy, threshold: currentMultisigInvolved?.threshold, @@ -112,17 +109,32 @@ const DeepTxCreationModal = ({ onClose() }, [onClose]) - const signCallback = useSigningCallback({ onSuccess, onSubmitting }) + const signCallback = useSigningCallback({ + onSuccess: () => { + onSuccess && onSuccess() + // // poll for 1min if the tx may make changes + // // such as creating a proxy, adding/removing a multisig + if (mustSubmitCallData) { + setRefetchMultisigTimeoutMinutes(1) + } + }, + onSubmitting, + onError: () => setIsSubmitting(false) + }) useEffect(() => { - if (!!parentCallInfo?.call && parentCallInfo.call.hash.toHex() !== proposalData.hash) { + const hash = + !!parentCallInfo?.call && + hashFromTx(parentCallInfo?.call?.getEncodedData(compatibilityToken as any).asHex()) + + if (hash !== proposalData.hash) { setErrorMessage("The callData provided doesn't match with the on-chain transaction") return } - }, [parentCallInfo, proposalData]) + }, [compatibilityToken, parentCallInfo, proposalData]) useEffect(() => { - if (!multisigProposalNeededFunds.isZero() && !hasSignerEnoughFunds) { + if (multisigProposalNeededFunds !== 0n && !hasSignerEnoughFunds) { const requiredBalanceString = formatBnBalance( multisigProposalNeededFunds, chainInfo?.tokenDecimals, @@ -149,8 +161,8 @@ const DeepTxCreationModal = ({ return } - if (!selectedAccount) { - const error = 'No selected address or multisig/proxy' + if (!selectedSigner) { + const error = 'No selected signer or multisig/proxy' console.error(error) setErrorMessage(error) return @@ -173,39 +185,8 @@ const DeepTxCreationModal = ({ setIsSubmitting(true) - fullTx - .signAndSend( - selectedAccount.address, - { signer: selectedSigner, withSignedTransaction: true }, - signCallback - ) - .then(() => { - // poll for 1min if the tx may make changes - // such as creating a proxy, adding/removing a multisig - if (mustSubmitCallData) { - setRefetchMultisigTimeoutMinutes(1) - } - }) - .catch((error: Error) => { - setIsSubmitting(false) - addToast({ - title: error.message, - type: 'error', - link: getSubscanExtrinsicLink(fullTx.hash.toHex()) - }) - }) - }, [ - api, - selectedAccount, - mustSubmitCallData, - parentCallInfo, - fullTx, - selectedSigner, - signCallback, - setRefetchMultisigTimeoutMinutes, - addToast, - getSubscanExtrinsicLink - ]) + fullTx.signSubmitAndWatch(selectedSigner, { at: 'best' }).subscribe(signCallback) + }, [api, mustSubmitCallData, parentCallInfo, fullTx, selectedSigner, signCallback]) const onAddedCallDataChange = useCallback( (event: ChangeEvent) => { diff --git a/packages/ui/src/contexts/ApiContext.tsx b/packages/ui/src/contexts/ApiContext.tsx index fd90f25c..686c5116 100644 --- a/packages/ui/src/contexts/ApiContext.tsx +++ b/packages/ui/src/contexts/ApiContext.tsx @@ -51,6 +51,7 @@ export interface IApiContext { api?: ApiType chainInfo?: ChainInfoHuman client?: PolkadotClient + compatibilityToken?: unknown } interface ChainInfoHuman { @@ -67,6 +68,7 @@ const ApiContextProvider = ({ children }: ApiContextProps) => { const [chainInfo, setChainInfo] = useState() const [client, setClient] = useState() const [api, setApi] = useState() + const [compatibilityToken, setCompatibilityToken] = useState() useEffect(() => { if (!selectedNetworkInfo) return @@ -158,12 +160,19 @@ const ApiContextProvider = ({ children }: ApiContextProps) => { }) }, [client]) + useEffect(() => { + if (!api) return + + api.compatibilityToken.then(setCompatibilityToken) + }, [api]) + return ( {children} diff --git a/packages/ui/src/hooks/useGetMultisigTx.tsx b/packages/ui/src/hooks/useGetMultisigTx.tsx index 81c99197..86c79c63 100644 --- a/packages/ui/src/hooks/useGetMultisigTx.tsx +++ b/packages/ui/src/hooks/useGetMultisigTx.tsx @@ -1,13 +1,12 @@ import { useMemo } from 'react' import { useApi } from '../contexts/ApiContext' import { MultiProxy } from '../contexts/MultiProxyContext' -import { SubmittableExtrinsic } from '@polkadot/api/types' -import { ISubmittableResult } from '@polkadot/types/types' import { useGetSortAddress } from './useGetSortAddress' import { getAsMultiTx } from '../utils/getAsMultiTx' -import { Weight } from '@polkadot/types/interfaces' -import { HexString, MultisigStorageInfo } from '../types' +import { HexString, MultisigStorageInfo, Weight } from '../types' import { getApproveAsMultiTx } from '../utils' +import { Transaction, TypedApi } from 'polkadot-api' +import { dot, MultiAddress } from '@polkadot-api/descriptors' interface Params { selectedMultisig?: MultiProxy['multisigs'][0] @@ -15,7 +14,7 @@ interface Params { senderAddress?: string fromAddress?: string isProxy?: boolean - extrinsicToCall?: SubmittableExtrinsic<'promise', ISubmittableResult> | undefined + extrinsicToCall?: Transaction | undefined weight?: Weight when?: MultisigStorageInfo['when'] forceAsMulti?: boolean @@ -36,7 +35,7 @@ export const useGetMultisigTx = ({ forceAsMulti = true, approveAsMultiHash }: Params) => { - const { api } = useApi() + const { api, compatibilityToken } = useApi() const { getSortAddress } = useGetSortAddress() const multisigTx = useMemo(() => { @@ -81,19 +80,23 @@ export const useGetMultisigTx = ({ return } - let tx: SubmittableExtrinsic<'promise'> | undefined + let tx: Transaction | undefined try { // the proxy is selected if (isProxy && !!extrinsicToCall) { - tx = api.tx.proxy.proxy(fromAddress, null, extrinsicToCall) + tx = (api as TypedApi).tx.Proxy.proxy({ + real: MultiAddress.Id(fromAddress), + force_proxy_type: undefined, + call: extrinsicToCall.decodedCall + }) // a multisig is selected } else { tx = extrinsicToCall } return forceAsMulti || approvalLength >= threshold - 1 - ? getAsMultiTx({ api, threshold, otherSignatories, tx, weight, when }) + ? getAsMultiTx({ api, threshold, otherSignatories, tx, weight, when, compatibilityToken }) : getApproveAsMultiTx({ api, threshold, @@ -118,7 +121,8 @@ export const useGetMultisigTx = ({ approvalLength, weight, when, - approveAsMultiHash + approveAsMultiHash, + compatibilityToken ]) return multisigTx diff --git a/packages/ui/src/hooks/usePendingTx.tsx b/packages/ui/src/hooks/usePendingTx.tsx index b85dc146..24a4708c 100644 --- a/packages/ui/src/hooks/usePendingTx.tsx +++ b/packages/ui/src/hooks/usePendingTx.tsx @@ -4,7 +4,6 @@ import { HexString, MultisigStorageInfo } from '../types' import { useMultisigCallQuery } from './useQueryMultisigCalls' import { isEmptyArray } from '../utils' import { useAccountId } from './useAccountId' -import { ApiPromise } from '@polkadot/api' import { ApiType, useApi } from '../contexts/ApiContext' import { ISanitizedCall, getDisplayArgs, isProxyCall, parseGenericCall } from '../utils' import { GenericCall } from '@polkadot/types' diff --git a/packages/ui/src/hooks/useProxyAdditionNeededFunds.tsx b/packages/ui/src/hooks/useProxyAdditionNeededFunds.tsx index be252146..1b6a12f7 100644 --- a/packages/ui/src/hooks/useProxyAdditionNeededFunds.tsx +++ b/packages/ui/src/hooks/useProxyAdditionNeededFunds.tsx @@ -1,22 +1,23 @@ import { useEffect, useState } from 'react' import { useApi } from '../contexts/ApiContext' -import BN from 'bn.js' +import { TypedApi } from 'polkadot-api' +import { dot } from '@polkadot-api/descriptors' export const useProxyAdditionNeededFunds = () => { const { api, chainInfo } = useApi() - const [min, setMin] = useState(new BN(0)) + const [min, setMin] = useState(0n) useEffect(() => { if (!api) return if (!chainInfo?.tokenDecimals) return - if (!api.consts?.proxy?.proxyDepositFactor) return - - // the proxy is already created (with proxyDepositBase already deposited by the first account - // that added the first proxy) we are only adding one account as proxy - const reserved = api.consts?.proxy?.proxyDepositFactor as unknown as BN - setMin(reserved) + if (!(api as TypedApi).constants?.Proxy?.ProxyDepositFactor) + return // the proxy is already created (with proxyDepositBase already deposited by the first account + // that added the first proxy) we are only adding one account as proxy + ;(api as TypedApi).constants.Proxy.ProxyDepositBase() + .then(setMin) + .catch(console.error) }, [api, chainInfo]) return { proxyAdditionNeededFunds: min } diff --git a/packages/ui/src/hooks/useWalletConnectNamespace.tsx b/packages/ui/src/hooks/useWalletConnectNamespace.tsx index 3644b00c..324788c4 100644 --- a/packages/ui/src/hooks/useWalletConnectNamespace.tsx +++ b/packages/ui/src/hooks/useWalletConnectNamespace.tsx @@ -1,13 +1,19 @@ -import { useCallback, useMemo } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import { useApi } from '../contexts/ApiContext' export const useGetWalletConnectNamespace = () => { - const { api } = useApi() - const genesisTruncated = useMemo(() => { - if (!api) return '' + const { client } = useApi() + const [genesisHash, setGenesisHash] = useState('') + + useEffect(() => { + client + ?.getChainSpecData() + .then((data) => setGenesisHash(data.genesisHash)) + .catch(console.error) + }, [client]) + + const genesisTruncated = useMemo(() => genesisHash.substring(2, 34), [genesisHash]) - return api.genesisHash.toHex().substring(2, 34) - }, [api]) const namespace = useMemo(() => `polkadot:${genesisTruncated}`, [genesisTruncated]) const getAccountsWithNamespace = useCallback( diff --git a/packages/ui/src/types.ts b/packages/ui/src/types.ts index eedd8893..b6da6c92 100644 --- a/packages/ui/src/types.ts +++ b/packages/ui/src/types.ts @@ -1,5 +1,4 @@ -import { GenericCall } from '@polkadot/types' -import { Weight } from '@polkadot/types/interfaces' +import { Transaction } from 'polkadot-api' export interface MultisigStorageInfo { approvals: string[] @@ -20,8 +19,10 @@ export enum AccountBadge { export type HexString = `0x${string}` export interface SubmittingCall { - call?: GenericCall + call?: Transaction method?: string section?: string - weight?: { ref_time: bigint; proof_size: bigint } + weight?: Weight } + +export type Weight = { ref_time: bigint; proof_size: bigint } diff --git a/packages/ui/src/utils/getApproveAsMultiTx.ts b/packages/ui/src/utils/getApproveAsMultiTx.ts index 3b9733d9..9add5ca0 100644 --- a/packages/ui/src/utils/getApproveAsMultiTx.ts +++ b/packages/ui/src/utils/getApproveAsMultiTx.ts @@ -1,8 +1,9 @@ -import { ApiPromise } from '@polkadot/api' +import { FixedSizeBinary } from 'polkadot-api' +import { ApiType } from '../contexts/ApiContext' import { HexString, MultisigStorageInfo } from '../types' interface Params { - api: ApiPromise + api: ApiType threshold: number otherSignatories: string[] when?: MultisigStorageInfo['when'] @@ -12,8 +13,14 @@ interface Params { export const getApproveAsMultiTx = ({ api, threshold, otherSignatories, hash, when }: Params) => { if (!hash) return - return api.tx.multisig.approveAsMulti(threshold, otherSignatories, when || null, hash, { - refTime: 0, - proofSize: 0 + return api.tx.Multisig.approve_as_multi({ + threshold, + other_signatories: otherSignatories, + maybe_timepoint: when, + call_hash: FixedSizeBinary.fromHex(hash), + max_weight: { + ref_time: 0n, + proof_size: 0n + } }) } diff --git a/packages/ui/src/utils/getAsMultiTx.ts b/packages/ui/src/utils/getAsMultiTx.ts index 66cc64bf..e4937cdc 100644 --- a/packages/ui/src/utils/getAsMultiTx.ts +++ b/packages/ui/src/utils/getAsMultiTx.ts @@ -1,6 +1,6 @@ import { MultisigStorageInfo } from '../types' import { Binary, HexString, Transaction } from 'polkadot-api' -import { ApiType } from '../contexts/ApiContext' +import { ApiType, IApiContext } from '../contexts/ApiContext' interface Params { api: ApiType @@ -10,27 +10,30 @@ interface Params { callData?: HexString weight?: { ref_time: bigint; proof_size: bigint } when?: MultisigStorageInfo['when'] + compatibilityToken: IApiContext['compatibilityToken'] } // TODO check if we can do this with papi // const LEGACY_ASMULTI_PARAM_LENGTH = 6 -export const getAsMultiTx = async ({ +export const getAsMultiTx = ({ api, threshold, otherSignatories, callData, tx, weight, - when -}: Params): Promise | undefined> => { + when, + compatibilityToken +}: Params): Transaction | undefined => { // we can pass either the tx, or the callData if (!callData && !tx) return + if (!compatibilityToken) return let txToSend: Transaction | undefined = tx if (!txToSend && callData) { - txToSend = await api.txFromCallData(Binary.fromHex(callData)) + txToSend = api.txFromCallData(Binary.fromHex(callData), compatibilityToken as any) } if (!txToSend) return diff --git a/packages/ui/src/utils/txHash.ts b/packages/ui/src/utils/txHash.ts new file mode 100644 index 00000000..6c3cb061 --- /dev/null +++ b/packages/ui/src/utils/txHash.ts @@ -0,0 +1,5 @@ +import { HexString } from 'polkadot-api' +import { Blake2256 } from '@polkadot-api/substrate-bindings' +import { fromHex, toHex } from '@polkadot-api/utils' + +export const hashFromTx = (tx: HexString) => toHex(Blake2256(fromHex(tx)))