diff --git a/packages/ui/src/components/MultixIdenticon.tsx b/packages/ui/src/components/MultixIdenticon.tsx index 9ce2f6e8..494d1808 100644 --- a/packages/ui/src/components/MultixIdenticon.tsx +++ b/packages/ui/src/components/MultixIdenticon.tsx @@ -1,9 +1,9 @@ import { useCallback, useState } from 'react' import Tooltip from '@mui/material/Tooltip' -import { ICON_SIZE_MEDIUM, ICON_THEME } from '../constants' +import { ICON_SIZE_MEDIUM, DEFAULT_ICON_THEME } from '../constants' import Identicon from '@polkadot/react-identicon' -import { IconTheme } from '@polkadot/react-identicon/types' import { styled } from '@mui/material/styles' +import { useApi } from '../contexts/ApiContext' const DEFAULT_PLACEMENT = 'top' const DEFAULT_TITLE = 'Address copied!' @@ -11,19 +11,14 @@ const DEFAULT_AUTO_HIDE_DURATION = 2000 interface Props { value?: string - theme?: IconTheme size?: number className?: string } -const MultixIdenticon = ({ - value, - theme = ICON_THEME, - size = ICON_SIZE_MEDIUM, - className -}: Props) => { +const MultixIdenticon = ({ value, size = ICON_SIZE_MEDIUM, className }: Props) => { const [open, setOpen] = useState(false) const handleTooltipClose = useCallback(() => setOpen(false), []) const handleTooltipOpen = useCallback(() => setOpen(true), []) + const { chainInfo } = useApi() return ( @@ -49,6 +44,10 @@ const MultixIdenticon = ({ const TooltipIconStyled = styled('div')` display: inherit; line-height: 0; + + img { + border-radius: 50%; + } ` export default MultixIdenticon diff --git a/packages/ui/src/components/Transactions/TransactionList.tsx b/packages/ui/src/components/Transactions/TransactionList.tsx index 37c53bef..e5f412e2 100644 --- a/packages/ui/src/components/Transactions/TransactionList.tsx +++ b/packages/ui/src/components/Transactions/TransactionList.tsx @@ -197,7 +197,7 @@ const TransactionList = ({ className }: Props) => { )} - {!pendingTxData.length && !isLoadingPendingTxs && ( + {Object.entries(aggregatedData).length === 0 && !isLoadingPendingTxs && ( {
You're all set!
)} - {!!pendingTxData.length && + {Object.entries(aggregatedData).length !== 0 && Object.entries(aggregatedData).map(([date, aggregatedData]) => { return ( diff --git a/packages/ui/src/components/modals/ChangeMultisig.tsx b/packages/ui/src/components/modals/ChangeMultisig.tsx index fc3b8530..ba951e22 100644 --- a/packages/ui/src/components/modals/ChangeMultisig.tsx +++ b/packages/ui/src/components/modals/ChangeMultisig.tsx @@ -16,7 +16,6 @@ import SignatorySelection from '../select/SignatorySelection' import Summary from '../../pages/Creation/Summary' import { useApi } from '../../contexts/ApiContext' import { useAccounts } from '../../contexts/AccountsContext' -import { createKeyMulti, sortAddresses } from '@polkadot/util-crypto' import { useSigningCallback } from '../../hooks/useSigningCallback' import { useToasts } from '../../contexts/ToastContext' import { AccountBadge } from '../../types' @@ -30,7 +29,8 @@ import { MdErrorOutline as ErrorOutlineIcon } from 'react-icons/md' import { useGetSubscanLinks } from '../../hooks/useSubscanLink' import { Button } from '../library' import { ModalCloseButton } from '../library/ModalCloseButton' -import { useGetEncodedAddress } from '../../hooks/useGetEncodedAddress' +import { useGetSortAddress } from '../../hooks/useGetSortAddress' +import { useGetMultisigAddress } from '../../contexts/useGetMultisigAddress' interface Props { onClose: () => void @@ -45,11 +45,11 @@ const ChangeMultisig = ({ onClose, className }: Props) => { const { api, chainInfo } = useApi() const { selectedMultiProxy, getMultisigAsAccountBaseInfo, getMultisigByAddress } = useMultiProxy() const { addToast } = useToasts() - const getEncodedAddress = useGetEncodedAddress() const signCallBack2 = useSigningCallback({ onSuccess: onClose, onError: onClose }) + const { getSortAddress } = useGetSortAddress() const { selectedAccount, selectedSigner, ownAddressList } = useAccounts() const [selectedMultisig, setSelectedMultisig] = useState(selectedMultiProxy?.multisigs[0]) const oldThreshold = useMemo(() => selectedMultisig?.threshold, [selectedMultisig]) @@ -67,14 +67,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => { ).length > 0, [ownAddressList, newSignatories, selectedMultisig?.signatories] ) - const newMultisigPubKey = useMemo(() => { - if (!newThreshold) return - return createKeyMulti(newSignatories, newThreshold) - }, [newSignatories, newThreshold]) - const newMultisigAddress = useMemo( - () => getEncodedAddress(newMultisigPubKey), - [getEncodedAddress, newMultisigPubKey] - ) + const newMultisigAddress = useGetMultisigAddress(newSignatories, newThreshold) const canGoNext = useMemo( () => newMultisigAddress !== selectedMultisig?.address, [newMultisigAddress, selectedMultisig] @@ -121,7 +114,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => { return } - const otherOldSignatories = sortAddresses( + const otherOldSignatories = getSortAddress( selectedMultisig.signatories.filter((sig) => sig !== selectedAccount.address) ) @@ -135,6 +128,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => { }, [ api, chainInfo, + getSortAddress, newMultisigAddress, newThreshold, oldThreshold, @@ -169,7 +163,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => { return } - const otherNewSignatories = sortAddresses( + const otherNewSignatories = getSortAddress( newSignatories.filter((sig) => sig !== selectedAccount.address) ) const removeProxyTx = api.tx.proxy.removeProxy(selectedMultisig?.address, 'Any', 0) @@ -181,6 +175,7 @@ const ChangeMultisig = ({ onClose, className }: Props) => { }, [ api, chainInfo, + getSortAddress, newSignatories, newThreshold, selectedAccount, diff --git a/packages/ui/src/components/modals/ProposalSigning.tsx b/packages/ui/src/components/modals/ProposalSigning.tsx index 32a2c757..5923f6d0 100644 --- a/packages/ui/src/components/modals/ProposalSigning.tsx +++ b/packages/ui/src/components/modals/ProposalSigning.tsx @@ -11,12 +11,12 @@ import SignerSelection from '../select/SignerSelection' import { SubmittableExtrinsic } from '@polkadot/api/types' import { useToasts } from '../../contexts/ToastContext' import { useSigningCallback } from '../../hooks/useSigningCallback' -import { sortAddresses } from '@polkadot/util-crypto' import { HexString, MultisigStorageInfo } from '../../types' import { useGetSubscanLinks } from '../../hooks/useSubscanLink' import { getDisplayArgs, getExtrinsicName } from '../../utils' import { useCallInfoFromCallData } from '../../hooks/useCallInfoFromCallData' import { ModalCloseButton } from '../library/ModalCloseButton' +import { useGetSortAddress } from '../../hooks/useGetSortAddress' export interface SigningModalProps { onClose: () => void @@ -70,7 +70,7 @@ const ProposalSigning = ({ }, [onClose]) const signCallback = useSigningCallback({ onSuccess, onSubmitting }) - + const { getSortAddress } = useGetSortAddress() useEffect(() => { if (isProposerSelected) { setAddedCallData(undefined) @@ -87,7 +87,7 @@ const ProposalSigning = ({ const onSign = useCallback( async (isApproving: boolean) => { - const otherSigners = sortAddresses( + const otherSigners = getSortAddress( signatories.filter((signer) => signer !== selectedAccount?.address) ) @@ -209,6 +209,7 @@ const ProposalSigning = ({ ) }, [ + getSortAddress, signatories, threshold, proposalData, @@ -216,10 +217,10 @@ const ProposalSigning = ({ selectedAccount, multisig, mustSubmitCallData, - addedCallData, callInfo, selectedSigner, signCallback, + addedCallData, addToast, getSubscanExtrinsicLink ] diff --git a/packages/ui/src/components/select/AccountSelection.tsx b/packages/ui/src/components/select/AccountSelection.tsx index 92f7e6d9..e49db7ba 100644 --- a/packages/ui/src/components/select/AccountSelection.tsx +++ b/packages/ui/src/components/select/AccountSelection.tsx @@ -9,6 +9,7 @@ import GenericAccountSelection, { AccountBaseInfo } from './GenericAccountSelect import { useAccountBaseFromAccountList } from '../../hooks/useAccountBaseFromAccountList' import { getOptionLabel } from '../../utils/getOptionLabel' import { getPubKeyFromAddress } from '../../utils/getPubKeyFromAddress' +import { useApi } from '../../contexts/ApiContext' interface Props { className?: string @@ -36,6 +37,7 @@ const AccountSelection = ({ withPreselection = true }: Props) => { const { getAccountByAddress } = useAccounts() + const { chainInfo } = useApi() const [errorMessage, setErrorMessage] = useState('') const { accountNames, addName } = useAccountNames() const [name, setName] = useState('') @@ -74,6 +76,28 @@ const AccountSelection = ({ return } + // if we are connected to a non eth network + // and adding eth accounts + if ( + !chainInfo?.isEthereum && + selected.address.length === 42 && + selected.address.startsWith('0x') + ) { + setErrorMessage('Ethereum addresses are not compatible with this network') + return + } + + // if we are connected to an eth network + // all addresses must be compatible + if ( + chainInfo?.isEthereum && + selected.address.length !== 42 && + !selected.address.startsWith('0x') + ) { + setErrorMessage('Non Ethereum address detected') + return + } + const pubkey = getPubKeyFromAddress(selected.address) if (pubkey && (currentSelectionPubKeys as string[]).includes(pubkey)) { setErrorMessage('Account already added') @@ -86,7 +110,7 @@ const AccountSelection = ({ setSelected(undefined) setName('') } - }, [selected, currentSelectionPubKeys, addAccount, name, addName]) + }, [selected, chainInfo, currentSelectionPubKeys, addAccount, name, addName]) const handleSpecialKeys = useCallback( (e: any) => { diff --git a/packages/ui/src/constants.ts b/packages/ui/src/constants.ts index caddeb47..0c9808c0 100644 --- a/packages/ui/src/constants.ts +++ b/packages/ui/src/constants.ts @@ -19,7 +19,7 @@ export const DAPP_NAME = 'Multix' export const ICON_SIZE_LARGE = 92 export const ICON_SIZE_MEDIUM = 40 export const ICON_SIZE_SMALL = 30 -export const ICON_THEME = 'polkadot' +export const DEFAULT_ICON_THEME = 'polkadot' export interface NetworkInfo { chainId: string @@ -37,128 +37,128 @@ export const networkList = { chainId: 'polkadot', explorerNetworkName: 'polkadot', rpcUrl: 'wss://rpc.polkadot.io', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: chainsPolkadotCircleSVG } as NetworkInfo, kusama: { chainId: 'kusama', explorerNetworkName: 'kusama', rpcUrl: 'wss://kusama-rpc.polkadot.io', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: chainsKusamaSVG } as NetworkInfo, 'assethub-dot': { chainId: 'assethub-polkadot', explorerNetworkName: 'assethub-polkadot', rpcUrl: 'wss://polkadot-asset-hub-rpc.polkadot.io', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: nodesAssetHubSVG } as NetworkInfo, 'assethub-ksm': { chainId: 'assethub-kusama', explorerNetworkName: 'assethub-kusama', rpcUrl: 'wss://kusama-asset-hub-rpc.polkadot.io', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: nodesAssetHubSVG } as NetworkInfo, acala: { chainId: 'acala', explorerNetworkName: 'acala', rpcUrl: 'wss://acala-rpc-3.aca-api.network/ws', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: chainsAcalaSVG } as NetworkInfo, // amplitude: { // chainId: 'amplitude', // explorerNetworkName: 'amplitude', // rpcUrl: 'wss://rpc-amplitude.pendulumchain.tech', - // wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - // httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + // wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + // httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', // logo: chainsAmplitudeSVG // } as NetworkInfo, astar: { chainId: 'astar', explorerNetworkName: 'astar', rpcUrl: 'wss://rpc.astar.network', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: nodesAstarPNG } as NetworkInfo, 'bifrost-dot': { chainId: 'bifrost-polkadot', explorerNetworkName: 'bifrost', rpcUrl: 'wss://bifrost-polkadot.api.onfinality.io/public-ws', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: nodesBifrostSVG } as NetworkInfo, hydradx: { chainId: 'hydradx', explorerNetworkName: 'hydradx', rpcUrl: 'wss://hydradx-rpc.dwellir.com', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: hydradxSVG } as NetworkInfo, interlay: { chainId: 'interlay', explorerNetworkName: 'interlay', rpcUrl: 'wss://interlay.api.onfinality.io/public-ws', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: nodesInterlaySVG } as NetworkInfo, khala: { chainId: 'khala', explorerNetworkName: 'khala', rpcUrl: 'wss://khala-api.phala.network/ws', - wsGraphqlUrl: 'wss:///squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https:///squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss:///squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https:///squid.subsquid.io/multix-large/v/v6/graphql', logo: nodesKhalaSVG } as NetworkInfo, // pendulum: { // chainId: 'pendulum', // explorerNetworkName: 'pendulum', // rpcUrl: 'wss://rpc-pendulum.prd.pendulumchain.tech', - // wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - // httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + // wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + // httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', // logo: chainsPendulumSVG // } as NetworkInfo, phala: { chainId: 'phala', explorerNetworkName: 'phala', rpcUrl: 'wss://api.phala.network/ws', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: phalaSVG } as NetworkInfo, 'rhala testnet': { chainId: 'rhala', explorerNetworkName: '', rpcUrl: 'wss://subbridge-test.phala.network/rhala/ws', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: nodesKhalaSVG } as NetworkInfo, rococo: { chainId: 'rococo', explorerNetworkName: 'rococo', rpcUrl: 'wss://rococo-rpc.polkadot.io', - wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', logo: chainsRococoSVG } as NetworkInfo, // westend: { // chainId: 'westend', // explorerNetworkName: 'westend', // rpcUrl: 'wss://westend-rpc.polkadot.io', - // wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v5/graphql', - // httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v5/graphql', + // wsGraphqlUrl: 'wss://squid.subsquid.io/multix-large/v/v6/graphql', + // httpGraphqlUrl: 'https://squid.subsquid.io/multix-large/v/v6/graphql', // logo: nodesWestendColourSVG // } as NetworkInfo, local: { diff --git a/packages/ui/src/contexts/AccountsContext.tsx b/packages/ui/src/contexts/AccountsContext.tsx index 8049f2ea..542cba18 100644 --- a/packages/ui/src/contexts/AccountsContext.tsx +++ b/packages/ui/src/contexts/AccountsContext.tsx @@ -67,51 +67,66 @@ const AccountContextProvider = ({ children }: AccountContextProps) => { setSelected(account) }, []) - const getaccountList = useCallback(async (): Promise => { - setIsAccountLoading(true) - - web3Enable(DAPP_NAME) - .then((ext) => { - setExtensions(ext) - }) - .catch(console.error) - - web3AccountsSubscribe( - (accountList) => { - if (accountList.length === 0) { - setIsExtensionError(true) - return - } - - setOwnAccountList([...accountList]) - - if (accountList.length > 0) { - const previousAccountAddress = localStorage.getItem(LOCALSTORAGE_SELECTED_ACCOUNT_KEY) - const account = previousAccountAddress && getAccountByAddress(previousAccountAddress) - - selectAccount(account || accountList[0]) + const getaccountList = useCallback( + async (isEthereum: boolean): Promise => { + setIsAccountLoading(true) + + web3Enable(DAPP_NAME) + .then((ext) => { + setExtensions(ext) + }) + .catch(console.error) + + web3AccountsSubscribe( + (accountList) => { + if (accountList.length === 0) { + setIsExtensionError(true) + return + } + + let listToPersist = accountList + //lower case ethereum addresses + if (isEthereum) { + listToPersist = accountList.map((account) => ({ + ...account, + address: account.address.toLowerCase() + })) + } + + setOwnAccountList([...listToPersist]) + + if (listToPersist.length > 0) { + const previousAccountAddress = localStorage.getItem(LOCALSTORAGE_SELECTED_ACCOUNT_KEY) + const account = previousAccountAddress && getAccountByAddress(previousAccountAddress) + + selectAccount(account || listToPersist[0]) + } + }, + { + ss58Format: chainInfo?.ss58Format, + accountType: isEthereum ? ['ethereum'] : undefined } - }, - { ss58Format: chainInfo?.ss58Format } - ).catch((error) => { - setIsExtensionError(true) - console.error(error) - }) + ).catch((error) => { + setIsExtensionError(true) + console.error(error) + }) - setIsAccountLoading(false) - }, [chainInfo, getAccountByAddress, selectAccount]) + setIsAccountLoading(false) + }, + [chainInfo, getAccountByAddress, selectAccount] + ) useEffect(() => { if (!isAllowedToConnectToExtension) return - if (isAccountLoading) return + if (isAccountLoading || !chainInfo) return if (extensions?.length === 0 && !ownAccountList.length) { if (!timeoutElapsed && isAllowedToConnectToExtension) { // give it another chance #ugly hack // race condition see https://github.com/polkadot-js/extension/issues/938 setTimeout(() => { - getaccountList() + getaccountList(chainInfo.isEthereum) setTimoutElapsed(true) }, 500) } else { @@ -124,7 +139,8 @@ const AccountContextProvider = ({ children }: AccountContextProps) => { getaccountList, isAccountLoading, isAllowedToConnectToExtension, - timeoutElapsed + timeoutElapsed, + chainInfo ]) useEffect(() => { @@ -132,10 +148,10 @@ const AccountContextProvider = ({ children }: AccountContextProps) => { if (ownAccountList.length > 0 || isAccountLoading) return // don't request before explicitely asking - if (isAllowedToConnectToExtension) { - getaccountList() + if (isAllowedToConnectToExtension && !!chainInfo) { + getaccountList(chainInfo.isEthereum) } - }, [ownAccountList, getaccountList, isAllowedToConnectToExtension, isAccountLoading]) + }, [ownAccountList, getaccountList, isAllowedToConnectToExtension, isAccountLoading, chainInfo]) useEffect(() => { if (!isAllowedToConnectToExtension) { diff --git a/packages/ui/src/contexts/ApiContext.tsx b/packages/ui/src/contexts/ApiContext.tsx index 9f954425..246a79e3 100644 --- a/packages/ui/src/contexts/ApiContext.tsx +++ b/packages/ui/src/contexts/ApiContext.tsx @@ -4,6 +4,7 @@ import { ApiOptions } from '@polkadot/api/types' import { TypeRegistry } from '@polkadot/types' import { useState, useEffect, createContext, useContext } from 'react' import { useNetwork } from './NetworkContext' +import { ethereumChains } from '../utils/ethereumChains' type ApiContextProps = { children: React.ReactNode | React.ReactNode[] @@ -21,6 +22,7 @@ interface ChainInfoHuman { ss58Format: number tokenDecimals: number tokenSymbol: string + isEthereum: boolean } interface RawChainInfoHuman { @@ -72,12 +74,13 @@ const ApiContextProvider = ({ children, types }: ApiContextProps) => { const info = api.registry.getChainProperties() const raw = info?.toHuman() as unknown as RawChainInfoHuman - + const isEthereum = ethereumChains.includes(api.runtimeVersion.specName.toString()) setChainInfo({ // some parachains such as interlay have a comma in the format, e.g: "2,042" ss58Format: Number(raw?.ss58Format.replace(',', '')) || 0, tokenDecimals: Number(raw?.tokenDecimals[0]) || 0, - tokenSymbol: raw?.tokenSymbol[0] || '' + tokenSymbol: raw?.tokenSymbol[0] || '', + isEthereum }) }) .catch(console.error) diff --git a/packages/ui/src/contexts/useGetMultisigAddress.tsx b/packages/ui/src/contexts/useGetMultisigAddress.tsx new file mode 100644 index 00000000..85531bea --- /dev/null +++ b/packages/ui/src/contexts/useGetMultisigAddress.tsx @@ -0,0 +1,24 @@ +import { useMemo } from 'react' +import { useApi } from './ApiContext' +import { createKeyMulti } from '@polkadot/util-crypto' +import { useGetEncodedAddress } from '../hooks/useGetEncodedAddress' + +export const useGetMultisigAddress = (signatories: string[], threshold?: number | null) => { + const { chainInfo } = useApi() + const getEncodedAddress = useGetEncodedAddress() + + const newMultisigPubKey = useMemo(() => { + if (!threshold) return + return createKeyMulti(signatories, threshold) + }, [signatories, threshold]) + const newMultisigAddress = useMemo( + () => getEncodedAddress(newMultisigPubKey), + [getEncodedAddress, newMultisigPubKey] + ) + + if (chainInfo?.isEthereum && newMultisigAddress?.startsWith('0x')) { + return newMultisigAddress.slice(0, 42) + } + + return newMultisigAddress +} diff --git a/packages/ui/src/hooks/useGetEncodedAddress.tsx b/packages/ui/src/hooks/useGetEncodedAddress.tsx index 676e4d99..50547454 100644 --- a/packages/ui/src/hooks/useGetEncodedAddress.tsx +++ b/packages/ui/src/hooks/useGetEncodedAddress.tsx @@ -1,6 +1,7 @@ import { useApi } from '../contexts/ApiContext' import { useCallback } from 'react' import { encodesubstrateAddress } from '../utils/encodeSubstrateAddress' +import { u8aToHex, isU8a } from '@polkadot/util' export const useGetEncodedAddress = () => { const { chainInfo } = useApi() @@ -11,6 +12,13 @@ export const useGetEncodedAddress = () => { return } + if (chainInfo?.isEthereum) { + const res = isU8a(address) + ? u8aToHex(address as Uint8Array).toString() + : (address as string) + return res.slice(0, 42) + } + return encodesubstrateAddress(address, chainInfo.ss58Format) }, [chainInfo] diff --git a/packages/ui/src/hooks/useGetMultisigTx.tsx b/packages/ui/src/hooks/useGetMultisigTx.tsx index bdfe79cf..e64fcfc5 100644 --- a/packages/ui/src/hooks/useGetMultisigTx.tsx +++ b/packages/ui/src/hooks/useGetMultisigTx.tsx @@ -1,9 +1,9 @@ import { useMemo } from 'react' import { useApi } from '../contexts/ApiContext' import { MultiProxy } from '../contexts/MultiProxyContext' -import { sortAddresses } from '@polkadot/util-crypto' import { SubmittableExtrinsic } from '@polkadot/api/types' import { ISubmittableResult } from '@polkadot/types/types' +import { useGetSortAddress } from './useGetSortAddress' interface Params { selectedMultisig?: MultiProxy['multisigs'][0] @@ -23,6 +23,7 @@ export const useGetMultisigTx = ({ extrinsicToCall }: Params) => { const { api } = useApi() + const { getSortAddress } = useGetSortAddress() const multisigTx = useMemo(() => { if (!selectedMultisig?.signatories) { @@ -30,7 +31,7 @@ export const useGetMultisigTx = ({ return } - const otherSigners = sortAddresses( + const otherSigners = getSortAddress( selectedMultisig.signatories.filter((signer) => signer !== senderAddress) ) @@ -69,7 +70,16 @@ export const useGetMultisigTx = ({ console.error('Error in multisigTx') console.error(e) } - }, [selectedMultisig, threshold, api, senderAddress, fromAddress, extrinsicToCall, isProxy]) + }, [ + selectedMultisig, + getSortAddress, + threshold, + api, + senderAddress, + fromAddress, + extrinsicToCall, + isProxy + ]) return multisigTx } diff --git a/packages/ui/src/hooks/useGetSortAddress.tsx b/packages/ui/src/hooks/useGetSortAddress.tsx new file mode 100644 index 00000000..80ee4257 --- /dev/null +++ b/packages/ui/src/hooks/useGetSortAddress.tsx @@ -0,0 +1,25 @@ +import { useApi } from '../contexts/ApiContext' +import { useCallback } from 'react' +import { sortAddresses } from '@polkadot/util-crypto' + +export const useGetSortAddress = () => { + const { chainInfo } = useApi() + + const getSortAddress = useCallback( + (addresses: string[]) => { + if ( + chainInfo?.isEthereum && + addresses.every((add) => { + return add.startsWith('0x') && add.length === 42 + }) + ) { + return addresses.sort() + } + + return sortAddresses(addresses) + }, + [chainInfo] + ) + + return { getSortAddress } +} diff --git a/packages/ui/src/hooks/usePendingTx.tsx b/packages/ui/src/hooks/usePendingTx.tsx index 3b1b80de..17fc1ff1 100644 --- a/packages/ui/src/hooks/usePendingTx.tsx +++ b/packages/ui/src/hooks/usePendingTx.tsx @@ -41,10 +41,16 @@ export const usePendingTx = (multiProxy?: MultiProxy) => { const multisigFromChain = (storage[0].toHuman() as Array)[0] const hash = (storage[0].toHuman() as Array)[1] const info = storage[1].toJSON() as unknown as MultisigStorageInfo + info.approvals = info.approvals.map((approval) => approval.toLowerCase()) // Fix for ghost proposals for https://github.com/polkadot-js/apps/issues/9103 // These 2 should be the same - if (multisigFromChain !== multisigs[index]) { + if (multisigFromChain.toLowerCase() !== multisigs[index].toLowerCase()) { + console.error( + 'The onchain call and the one found in the block donot correstpond', + multisigFromChain, + multisigs[index] + ) return } diff --git a/packages/ui/src/pages/Creation/index.tsx b/packages/ui/src/pages/Creation/index.tsx index 40a695b6..34824aa7 100644 --- a/packages/ui/src/pages/Creation/index.tsx +++ b/packages/ui/src/pages/Creation/index.tsx @@ -4,7 +4,6 @@ import { useCallback, useEffect, useMemo, useState } from 'react' import { styled } from '@mui/material/styles' import { useApi } from '../../contexts/ApiContext' import SignatorySelection from '../../components/select/SignatorySelection' -import { createKeyMulti, sortAddresses } from '@polkadot/util-crypto' import { useAccounts } from '../../contexts/AccountsContext' import ThresholdSelection from './ThresholdSelection' import NameSelection from './NameSelection' @@ -17,8 +16,10 @@ import { useCheckBalance } from '../../hooks/useCheckBalance' import { useMultisigProposalNeededFunds } from '../../hooks/useMultisigProposalNeededFunds' import { usePureProxyCreationNeededFunds } from '../../hooks/usePureProxyCreationNeededFunds' import { useGetSubscanLinks } from '../../hooks/useSubscanLink' -import { useGetEncodedAddress } from '../../hooks/useGetEncodedAddress' import WithProxySelection from './WitProxySelection' +import { useGetSortAddress } from '../../hooks/useGetSortAddress' +import { useGetMultisigAddress } from '../../contexts/useGetMultisigAddress' +import { isEthereumAddress } from '@polkadot/util-crypto' interface Props { className?: string @@ -30,13 +31,14 @@ const MultisigCreation = ({ className }: Props) => { const [signatories, setSignatories] = useState([]) const [currentStep, setCurrentStep] = useState(0) const isLastStep = useMemo(() => currentStep === steps.length - 1, [currentStep]) - const { api } = useApi() + const { api, chainInfo } = useApi() const [threshold, setThreshold] = useState() const { selectedSigner, selectedAccount, ownAddressList } = useAccounts() const navigate = useNavigate() const signCallBack = useSigningCallback({ onSuccess: () => navigate('/?creationInProgress=true') }) + const { getSortAddress } = useGetSortAddress() const { addToast } = useToasts() const [name, setName] = useState('') const { addName } = useAccountNames() @@ -47,16 +49,12 @@ const MultisigCreation = ({ className }: Props) => { ) const [errorMessage, setErrorMessage] = useState('') const { pureProxyCreationNeededFunds } = usePureProxyCreationNeededFunds() - const supportsProxy = useMemo(() => !!api && !!api.tx.proxy, [api]) - const multisigPubKey = useMemo(() => { - if (!threshold) return - return createKeyMulti(signatories, threshold) - }, [signatories, threshold]) - const getEncodedAddress = useGetEncodedAddress() - const multiAddress = useMemo( - () => getEncodedAddress(multisigPubKey), - [getEncodedAddress, multisigPubKey] - ) + const supportsProxy = useMemo(() => { + const hasProxyPallet = !!api && !!api.tx.proxy + // Moonbeam and moonriver have the pallet, but it's deactivated + return hasProxyPallet && !chainInfo?.isEthereum + }, [api, chainInfo]) + const multiAddress = useGetMultisigAddress(signatories, threshold) const [withProxy, setWithProxy] = useState(false) const remarkCall = useMemo(() => { if (withProxy) { @@ -88,7 +86,7 @@ const MultisigCreation = ({ className }: Props) => { return } - const otherSignatories = sortAddresses( + const otherSignatories = getSortAddress( signatories.filter((sig) => sig !== selectedAccount.address) ) const remarkTx = api.tx.system.remark(`Multix creation ${multiAddress}`) @@ -96,7 +94,7 @@ const MultisigCreation = ({ className }: Props) => { refTime: 0, proofSize: 0 }) - }, [api, multiAddress, selectedAccount, signatories, threshold, withProxy]) + }, [api, getSortAddress, multiAddress, selectedAccount, signatories, threshold, withProxy]) const batchCall = useMemo(() => { if (!withProxy) { @@ -127,7 +125,7 @@ const MultisigCreation = ({ className }: Props) => { return } - const otherSignatories = sortAddresses( + const otherSignatories = getSortAddress( signatories.filter((sig) => sig !== selectedAccount.address) ) const proxyTx = api.tx.proxy.createPure('Any', 0, 0) @@ -144,6 +142,7 @@ const MultisigCreation = ({ className }: Props) => { return api.tx.utility.batchAll([transferTx, multiSigProxyCall]) }, [ api, + getSortAddress, multiAddress, pureProxyCreationNeededFunds, selectedAccount, @@ -158,8 +157,11 @@ const MultisigCreation = ({ className }: Props) => { call: withProxy ? batchCall : remarkCall }) const neededBalance = useMemo( - () => pureProxyCreationNeededFunds.add(multisigProposalNeededFunds), - [multisigProposalNeededFunds, pureProxyCreationNeededFunds] + () => + withProxy + ? pureProxyCreationNeededFunds.add(multisigProposalNeededFunds) + : multisigProposalNeededFunds, + [multisigProposalNeededFunds, pureProxyCreationNeededFunds, withProxy] ) const { hasEnoughFreeBalance: hasSignerEnoughFunds } = useCheckBalance({ min: neededBalance, @@ -186,8 +188,25 @@ const MultisigCreation = ({ className }: Props) => { return false } + // we are on an ethereum network, all addresses must be eth addresses + if (chainInfo?.isEthereum) { + return signatories.every((signatory) => isEthereumAddress(signatory)) + } + + // we are on a non ethereum network, no address should be an ethereum one + if (!chainInfo?.isEthereum) { + return signatories.every((signatory) => !isEthereumAddress(signatory)) + } + return true - }, [currentStep, hasSignerEnoughFunds, ownAccountPartOfSignatories, signatories, threshold]) + }, [ + chainInfo?.isEthereum, + currentStep, + hasSignerEnoughFunds, + ownAccountPartOfSignatories, + signatories, + threshold + ]) useEffect(() => { // default to using a proxy @@ -457,7 +476,7 @@ export default styled(MultisigCreation)( padding-bottom: 2rem; .infoBox { - margin-bottom: 1rem; + margin-top: 1rem; } .stepItem { diff --git a/packages/ui/src/utils/encodeSubstrateAddress.ts b/packages/ui/src/utils/encodeSubstrateAddress.ts index 4f13ed1c..097e9657 100644 --- a/packages/ui/src/utils/encodeSubstrateAddress.ts +++ b/packages/ui/src/utils/encodeSubstrateAddress.ts @@ -1,9 +1,10 @@ import { encodeAddress } from '@polkadot/util-crypto' export const encodesubstrateAddress = (address: string | Uint8Array, ss58Format: number) => { + // this looks like an ethereum account, do not encode if (typeof address === 'string' && address.startsWith('0x') && address.length === 42) { - console.log('invalid address format to encode', address) - return address + // console.log('Ethereum address detected, not encoding', address) + return address.toLowerCase() } try { diff --git a/packages/ui/src/utils/ethereumChains.ts b/packages/ui/src/utils/ethereumChains.ts new file mode 100644 index 00000000..bc441542 --- /dev/null +++ b/packages/ui/src/utils/ethereumChains.ts @@ -0,0 +1,34 @@ +// Copyright 2017-2023 @polkadot/apps-config authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +// The list of Ethereum networks, for these the UI will default to Ethereum-only accounts + +export const ethereumChains = [ + 'mythical-devnet', + 'frontier-template', + 'jaz', + 'moonbase', + 'moonbeam', + 'moonriver', + 'moonsama', + 'moonshadow', + 'altbeacon', + 'alt-producer', + 'flash-layer', + 'armonia-eva', + 'armonia-wall-e', + 'root', + 'Darwinia2', + 'Crab2', + 'Pangolin2', + 'Pangoro2', + 'thebifrost-dev', + 'thebifrost-testnet', + 'thebifrost-mainnet', + 'dracones', + 'dracones-dwarf', + 'subspace-evm-domain', + 'ferrum-parachain', + 'quantum-portal-network-parachain', + 'peerplays' +] diff --git a/packages/ui/src/utils/getPubKeyFromAddress.ts b/packages/ui/src/utils/getPubKeyFromAddress.ts index 39704285..7359e1a5 100644 --- a/packages/ui/src/utils/getPubKeyFromAddress.ts +++ b/packages/ui/src/utils/getPubKeyFromAddress.ts @@ -3,8 +3,9 @@ import { decodeAddress } from '@polkadot/util-crypto' import { HexString } from '../types' const decode = (address: string) => { - if (address.startsWith('0x')) { - return null + // if it's an ethereum address pass just return it + if (address.startsWith('0x') && address.length === 42) { + return address.toLowerCase() } try { diff --git a/packages/ui/src/utils/isValidAddress.ts b/packages/ui/src/utils/isValidAddress.ts index ea0de6f2..257b69b0 100644 --- a/packages/ui/src/utils/isValidAddress.ts +++ b/packages/ui/src/utils/isValidAddress.ts @@ -7,6 +7,10 @@ export const isValidAddress = (address: string | Uint8Array | null | undefined) return true } catch (error) { + // if it's an ethereum address it can't be decoded but could still be valid + if (typeof address === 'string' && address.startsWith('0x') && address.length === 42) { + return true + } return false } } diff --git a/squid/assets/envs/.env.moonbeam b/squid/assets/envs/.env.moonbeam new file mode 100644 index 00000000..60caa8bb --- /dev/null +++ b/squid/assets/envs/.env.moonbeam @@ -0,0 +1,6 @@ +BLOCK_START=3000000 +PREFIX=1284 +RPC_WS="wss://moonbeam.api.onfinality.io/public-ws" +ARCHIVE_NAME="moonbeam" +CHAIN_ID='moonbeam' +IS_ETHEREUM='true' \ No newline at end of file diff --git a/squid/assets/envs/.env.moonriver b/squid/assets/envs/.env.moonriver new file mode 100644 index 00000000..460a6819 --- /dev/null +++ b/squid/assets/envs/.env.moonriver @@ -0,0 +1,6 @@ +BLOCK_START=3000000 +PREFIX=1285 +RPC_WS="wss://moonriver.api.onfinality.io/public-ws" +ARCHIVE_NAME="moonriver" +CHAIN_ID='moonriver' +IS_ETHEREUM='true' \ No newline at end of file diff --git a/squid/commands.json b/squid/commands.json index 06437707..e1508b4f 100644 --- a/squid/commands.json +++ b/squid/commands.json @@ -160,6 +160,26 @@ "lib/main", "dotenv_config_path=assets/envs/.env.interlay" ] + }, + "start-moonriver": { + "description": "starts the indexer with moonriver", + "cmd": [ + "node", + "-r", + "dotenv/config", + "lib/main", + "dotenv_config_path=assets/envs/.env.moonriver" + ] + }, + "start-moonbeam": { + "description": "starts the indexer with moonbeam", + "cmd": [ + "node", + "-r", + "dotenv/config", + "lib/main", + "dotenv_config_path=assets/envs/.env.moonbeam" + ] } } } diff --git a/squid/squid-manifests/large-squid.yaml b/squid/squid-manifests/large-squid.yaml index 8e0651e4..7a8c4e99 100644 --- a/squid/squid-manifests/large-squid.yaml +++ b/squid/squid-manifests/large-squid.yaml @@ -1,6 +1,6 @@ manifestVersion: subsquid.io/v0.1 name: multix-large -version: 5 +version: 6 description: |- Squid for Multix @@ -34,6 +34,10 @@ deploy: cmd: ['sqd', 'start-astar'] - name: hydradx-processor cmd: ['sqd', 'start-hydradx'] + - name: moonbeam-processor + cmd: ['sqd', 'start-moonbeam'] + - name: moonriver-processor + cmd: ['sqd', 'start-moonriver'] - name: khala-processor cmd: ['sqd', 'start-khala'] # - name: pendulum-processor diff --git a/squid/src/multisigCalls.ts b/squid/src/multisigCalls.ts index eed84a54..8b36b7e5 100644 --- a/squid/src/multisigCalls.ts +++ b/squid/src/multisigCalls.ts @@ -1,4 +1,3 @@ -import { decodeHex } from '@subsquid/substrate-processor' import { encodeId } from './util/accountEncoding' // "args": { @@ -29,9 +28,9 @@ import { encodeId } from './util/accountEncoding' // }, export const handleMultisigCall = (multisigArgs: any) => { - const encodedOtherSignatories = multisigArgs['otherSignatories'].map((signatory: string) => - encodeId(decodeHex(signatory)) - ) + const encodedOtherSignatories = multisigArgs['otherSignatories'].map((signatory: string) => { + return encodeId(signatory) + }) return { otherSignatories: encodedOtherSignatories, diff --git a/squid/src/util/Env.ts b/squid/src/util/Env.ts index 90eb8533..a7cf9977 100644 --- a/squid/src/util/Env.ts +++ b/squid/src/util/Env.ts @@ -8,6 +8,7 @@ interface EnvValues { archiveUrl?: string chainId: string genesis?: string + isEthereum?: boolean } export class Env { @@ -21,7 +22,8 @@ export class Env { archiveName: process.env.ARCHIVE_NAME || '', archiveUrl: process.env.ARCHIVE_URL || '', chainId: process.env.CHAIN_ID || '', - genesis: process.env.GENESIS || undefined + genesis: process.env.GENESIS || undefined, + isEthereum: process.env.IS_ETHEREUM === 'true' || false } this.checkForUndefined() diff --git a/squid/src/util/accountEncoding.ts b/squid/src/util/accountEncoding.ts index dd6eb9f8..8dfb135e 100644 --- a/squid/src/util/accountEncoding.ts +++ b/squid/src/util/accountEncoding.ts @@ -1,6 +1,12 @@ -import * as ss58 from '@subsquid/ss58' import { env } from '../main' +import { toHex } from '@subsquid/substrate-processor' +import { encodeAddress } from '@polkadot/util-crypto' +import { isUint8Array } from 'util/types' -export function encodeId(id: Uint8Array): string { - return ss58.codec(env.prefix).encode(id) +export function encodeId(id: string | Uint8Array): string { + if (env.isEthereum) { + return isUint8Array(id) ? toHex(id as Uint8Array).toString() : (id as string) + } + + return encodeAddress(id, env.prefix) } diff --git a/squid/src/util/getMultisigAddress.ts b/squid/src/util/getMultisigAddress.ts index 307cf6c2..9b7192ec 100644 --- a/squid/src/util/getMultisigAddress.ts +++ b/squid/src/util/getMultisigAddress.ts @@ -1,6 +1,15 @@ -import { createKeyMulti, encodeAddress } from '@polkadot/util-crypto' +import { createKeyMulti } from '@polkadot/util-crypto' +import { encodeId } from './accountEncoding' import { env } from '../main' export const getMultisigAddress = (signatories: (string | Uint8Array)[], threshold: number) => { - return encodeAddress(createKeyMulti(signatories, threshold), env.prefix) + const key = createKeyMulti(signatories, threshold) + const res = encodeId(key) + + // truncate the address at 42 chars for Ethereum addresses + if (env.isEthereum && res.startsWith('0x')) { + return res.slice(0, 42) + } + + return res } diff --git a/squid/src/util/getOriginAccount.ts b/squid/src/util/getOriginAccount.ts index b5dbe530..006d0ec7 100644 --- a/squid/src/util/getOriginAccount.ts +++ b/squid/src/util/getOriginAccount.ts @@ -1,15 +1,12 @@ -import { decodeHex } from '@subsquid/substrate-processor' import { encodeId } from './accountEncoding' -import { encodeAddress } from '@polkadot/util-crypto' -import { env } from '../main' export function getOriginAccount(origin: any): string { if (origin && origin.__kind === 'system' && origin.value.__kind === 'Signed') { const id = origin.value.value if (id.__kind === 'Id') { - return encodeAddress(encodeId(decodeHex(id.value)), env.prefix) + return encodeId(id.value) } else { - return encodeAddress(encodeId(decodeHex(id)), env.prefix) + return encodeId(id) } } else { throw new Error('Unexpected origin') diff --git a/squid/src/util/getProxyInfoFromArgs.ts b/squid/src/util/getProxyInfoFromArgs.ts index 42597eca..3c1da8a0 100644 --- a/squid/src/util/getProxyInfoFromArgs.ts +++ b/squid/src/util/getProxyInfoFromArgs.ts @@ -1,10 +1,10 @@ import { EventItem } from '@subsquid/substrate-processor/lib/interfaces/dataSelection' -import { encodeAddress } from '@polkadot/util-crypto' import { getProxyTypeFromRaw } from './getProxyTypeFromRaw' import { getProxyAccountId } from './getProxyAccountId' -import { Ctx, dataEvent, env } from '../main' +import { Ctx, dataEvent } from '../main' import { ProxyType } from '../types/v9111' import { JsonLog } from './JsonLog' +import { encodeId } from './accountEncoding' interface Params { item: EventItem<'Proxy.ProxyAdded' | 'Proxy.ProxyRemoved', (typeof dataEvent)['data']> @@ -27,9 +27,8 @@ export const getProxyInfoFromArgs = ({ item, chainId, ctx }: Params) => { ctx.log.error(`The proxy could not be determined ${JsonLog(item)}`) return } - - const _delegator = (delegator && encodeAddress(delegator, env.prefix)) || '' - const _delegatee = (delegatee && encodeAddress(delegatee, env.prefix)) || '' + const _delegator = (delegator && encodeId(delegator)) || '' + const _delegatee = (delegatee && encodeId(delegatee)) || '' const _type = getProxyTypeFromRaw(proxyType.__kind) const _delay = Number(delay) const _id = getProxyAccountId(_delegatee, _delegator, _type, _delay, chainId) diff --git a/squid/src/util/getPureProxyInfoFromArgs.ts b/squid/src/util/getPureProxyInfoFromArgs.ts index e44abb76..4648d10f 100644 --- a/squid/src/util/getPureProxyInfoFromArgs.ts +++ b/squid/src/util/getPureProxyInfoFromArgs.ts @@ -1,10 +1,10 @@ import { EventItem } from '@subsquid/substrate-processor/lib/interfaces/dataSelection' -import { encodeAddress } from '@polkadot/util-crypto' import { getProxyAccountId } from './getProxyAccountId' -import { Ctx, dataEvent, env } from '../main' +import { Ctx, dataEvent } from '../main' import { getProxyTypeFromRaw } from './getProxyTypeFromRaw' import { ProxyType as ProxyTypeV2005 } from '../types/v2005' import { JsonLog } from './JsonLog' +import { encodeId } from './accountEncoding' interface Params { item: EventItem<'Proxy.PureCreated' | 'Proxy.AnonymousCreated', (typeof dataEvent)['data']> @@ -31,8 +31,8 @@ export const getPureProxyInfoFromArgs = ({ item, chainId, isAnonymous, ctx }: Pa return } - const _who = (who && encodeAddress(who, env.prefix)) || '' - const _pure = (pure && encodeAddress(pure, env.prefix)) || '' + const _who = (who && encodeId(who)) || '' + const _pure = (pure && encodeId(pure)) || '' const _type = getProxyTypeFromRaw(proxyType.__kind) const id = getProxyAccountId(_who, _pure, _type, disambiguationIndex, chainId)