Skip to content

Commit

Permalink
decodedCall
Browse files Browse the repository at this point in the history
  • Loading branch information
Tbaut committed Sep 19, 2024
1 parent 3bcf704 commit 239dcae
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 59 deletions.
28 changes: 16 additions & 12 deletions packages/ui/src/components/EasySetup/BalancesTransfer.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
import { Box, InputAdornment } from '@mui/material'
import { styled } from '@mui/material/styles'
import { SubmittableExtrinsic } from '@polkadot/api/types'
import { ISubmittableResult } from '@polkadot/types/types'
import GenericAccountSelection, { AccountBaseInfo } from '../select/GenericAccountSelection'
import { ReactNode, useCallback, useEffect, useMemo, useState } from 'react'
import { useApi } from '../../contexts/ApiContext'
import { useCheckBalance } from '../../hooks/useCheckBalance'
import BN from 'bn.js'
import { getGlobalMaxValue, inputToBn } from '../../utils'
import { getGlobalMaxValue, inputToBigInt } from '../../utils'
import { TextField } from '../library'
import { getOptionLabel } from '../../utils/getOptionLabel'
import { useAccountBaseFromAccountList } from '../../hooks/useAccountBaseFromAccountList'
import { dot, MultiAddress } from '@polkadot-api/descriptors'
import { Transaction, TypedApi } from 'polkadot-api'

interface Props {
className?: string
from: string
onSetExtrinsic: (ext?: SubmittableExtrinsic<'promise', ISubmittableResult>) => void
onSetExtrinsic: (ext?: Transaction<any, any, any, any>) => void
onSetErrorMessage: React.Dispatch<React.SetStateAction<string | ReactNode>>
}

Expand All @@ -24,7 +23,7 @@ const BalancesTransfer = ({ className, onSetExtrinsic, onSetErrorMessage, from }
const [selected, setSelected] = useState<AccountBaseInfo | undefined>()
const { api, chainInfo } = useApi()
const [amountString, setAmountString] = useState('')
const [amount, setAmount] = useState<BN | undefined>()
const [amount, setAmount] = useState<bigint | undefined>()
const [amountError, setAmountError] = useState('')
const { hasEnoughFreeBalance } = useCheckBalance({
min: amount,
Expand Down Expand Up @@ -52,7 +51,12 @@ const BalancesTransfer = ({ className, onSetExtrinsic, onSetErrorMessage, from }
return
}

onSetExtrinsic(api.tx.balances.transferKeepAlive(toAddress, amount.toString()))
onSetExtrinsic(
(api as TypedApi<typeof dot>).tx.Balances.transfer_keep_alive({
dest: MultiAddress.Id(toAddress),
value: amount
})
)
}, [amount, api, chainInfo, onSetExtrinsic, toAddress])

const onAddressDestChange = useCallback((account: AccountBaseInfo) => {
Expand All @@ -68,7 +72,7 @@ const BalancesTransfer = ({ className, onSetExtrinsic, onSetErrorMessage, from }

if (!decimals) {
onSetErrorMessage('Invalid network decimals')
setAmount(new BN(0))
setAmount(0n)
return
}

Expand All @@ -78,19 +82,19 @@ const BalancesTransfer = ({ className, onSetExtrinsic, onSetErrorMessage, from }
if (!stringInput.match('^[0-9]+([.][0-9]+)?$')) {
setAmountError('Only numbers and "." are accepted.')
onSetErrorMessage('Invalid amount')
setAmount(new BN(0))
setAmount(0n)
return
}

const bnResult = inputToBn(decimals, stringInput)
const bigintResult = inputToBigInt(decimals, stringInput)

if (bnResult.gte(maxValue)) {
if (bigintResult > maxValue) {
setAmountError('Amount too large')
onSetErrorMessage('Amount too large')
return
}

setAmount(bnResult)
setAmount(bigintResult)
},
[chainInfo, maxValue, onSetErrorMessage]
)
Expand Down
44 changes: 22 additions & 22 deletions packages/ui/src/components/EasySetup/FromCallData.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,57 @@
import { Alert, Box } from '@mui/material'
import { styled } from '@mui/material/styles'
import { SubmittableExtrinsic } from '@polkadot/api/types'
import { ISubmittableResult } from '@polkadot/types/types'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
import React, { useCallback, useEffect, useState } from 'react'
import { useApi } from '../../contexts/ApiContext'
import { TextField } from '../library'
import CallInfo from '../CallInfo'
import { useCallInfoFromCallData } from '../../hooks/useCallInfoFromCallData'
import { HexString } from '../../types'
import { getDisplayArgs, getExtrinsicName } from '../../utils'
import { getExtrinsicName } from '../../utils'
import { usePjsLinks } from '../../hooks/usePjsLinks'
import { u8aToHex } from '@polkadot/util'
import { Binary, Transaction } from 'polkadot-api'

interface Props {
className?: string
onSetExtrinsic: (ext: SubmittableExtrinsic<'promise', ISubmittableResult>) => void
onSetExtrinsic: (ext: Transaction<any, any, any, any>) => void
}

const FromCallData = ({ className, onSetExtrinsic }: Props) => {
const { api } = useApi()
const [pastedCallData, setPastedCallData] = useState<HexString | undefined>(undefined)
const [callDataError, setCallDataError] = useState('')
const [isProxyProxyRemoved, setIsProxyProxyRemoved] = useState(false)
const [callDataToUse, setCallDataToUse] = useState<HexString | undefined>()

const removeProxyProxyCall = useCallback(
(call: HexString) => {
async (call: HexString) => {
setIsProxyProxyRemoved(false)
if (!api) return call

const proxyProxyString = u8aToHex(api?.tx.proxy?.proxy.callIndex).toString()
const decodedCall = (await api.txFromCallData(Binary.fromHex(call))).decodedCall

// check if this call is a proxy.proxy
if (!call.startsWith(proxyProxyString)) {
return call
if (decodedCall.type === 'Proxy' && decodedCall.value.type === 'proxy') {
// a proxy.proxy call is encoded with e.g
// callIndex 1e00
// real 00 eb53ed54b7f921a438923e6eb52c4d89afc5c0fed5d0d15fb78648c53da227a0
// forceProxyType 00
setIsProxyProxyRemoved(true)
return `0x${call.substring(74)}` as HexString
}

// a proxy.proxy call is encoded with e.g
// callIndex 1e00
// real 00 eb53ed54b7f921a438923e6eb52c4d89afc5c0fed5d0d15fb78648c53da227a0
// forceProxyType 00
setIsProxyProxyRemoved(true)
return `0x${call.substring(74)}` as HexString
return call
},
[api]
)

// users may erroneously paste callData from the multisig calldata
// this may start by proxy.proxy although this will be
// added by Multix too. For this reason we strip it.
const callDataToUse = useMemo(
() => pastedCallData && removeProxyProxyCall(pastedCallData),
[pastedCallData, removeProxyProxyCall]
)
useEffect(() => {
if (!pastedCallData) return
removeProxyProxyCall(pastedCallData).then(setCallDataToUse).catch(console.error)
}, [pastedCallData, removeProxyProxyCall])

const { callInfo } = useCallInfoFromCallData(callDataToUse)
const { callInfo: pastedCallInfo } = useCallInfoFromCallData(pastedCallData)
const { extrinsicUrl } = usePjsLinks()
Expand All @@ -65,7 +65,7 @@ const FromCallData = ({ className, onSetExtrinsic }: Props) => {
return
}

onSetExtrinsic(api.tx(callInfo.call))
onSetExtrinsic(callInfo.call)
}, [api, pastedCallData, callInfo, onSetExtrinsic])

const onCallDataChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
Expand Down Expand Up @@ -106,7 +106,7 @@ const FromCallData = ({ className, onSetExtrinsic }: Props) => {
{!!callInfo && !!pastedCallInfo && !callDataError && (
<CallInfo
aggregatedData={{
args: getDisplayArgs(callInfo.call),
args: callInfo.call?.decodedCall,
callData: callDataToUse,
name: getExtrinsicName(callInfo.section, callInfo.method)
}}
Expand Down
4 changes: 2 additions & 2 deletions packages/ui/src/components/EasySetup/ManualExtrinsic.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ISubmittableResult } from '@polkadot/types/types'
import React, { ChangeEvent, ReactNode, useCallback, useEffect, useMemo, useState } from 'react'
import { useApi } from '../../contexts/ApiContext'
import paramConversion from '../../utils/paramConversion'
import { getGlobalMaxValue, inputToBn } from '../../utils'
import { getGlobalMaxValue, inputToBigInt } from '../../utils'
import BN from 'bn.js'
import { isTypeBalanceWithBalanceCall } from '../../utils/isTypeBalance'

Expand Down Expand Up @@ -165,7 +165,7 @@ const ManualExtrinsic = ({
return previousValue
}

const bnResult = inputToBn(chainInfo.tokenDecimals, value)
const bnResult = inputToBigInt(chainInfo.tokenDecimals, value)

if (isAmountOverflow(bnResult)) {
return previousValue
Expand Down
41 changes: 18 additions & 23 deletions packages/ui/src/utils/bnUtils.ts
Original file line number Diff line number Diff line change
@@ -1,57 +1,52 @@
// Copyright 2017-2023 @polkadot/react-components authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { BN, BN_ONE, BN_TEN, BN_TWO, BN_ZERO } from '@polkadot/util'

const DEFAULT_BITLENGTH = 32 as BitLength

export type BitLength = 8 | 16 | 32 | 64 | 128 | 256

export function getGlobalMaxValue(bitLength?: number): BN {
return BN_TWO.pow(new BN(bitLength || DEFAULT_BITLENGTH)).isub(BN_ONE)
export function getGlobalMaxValue(bitLength?: number): bigint {
return 2n ** BigInt(bitLength || DEFAULT_BITLENGTH) - 1n
}

export function isValidNumber(
bn: BN,
bn: bigint,
bitLength: BitLength,
isSigned: boolean,
isZeroable: boolean,
maxValue?: BN | null
maxValue?: bigint | null
): boolean {
if (
// cannot be negative
(!isSigned && bn.lt(BN_ZERO)) ||
(!isSigned && bn < 0n) ||
// cannot be > than allowed max
bn.gt(getGlobalMaxValue(bitLength)) ||
bn > getGlobalMaxValue(bitLength) ||
// check if 0 and it should be a value
(!isZeroable && bn.isZero()) ||
(!isZeroable && bn === 0n) ||
// check that the bitlengths fit
bn.bitLength() > (bitLength || DEFAULT_BITLENGTH) ||
bn.toString(2).length > (bitLength || DEFAULT_BITLENGTH) ||
// cannot be > max (if specified)
(maxValue && maxValue.gtn(0) && bn.gt(maxValue))
(maxValue && maxValue > 0n && bn > maxValue)
) {
return false
}

return true
}

export function inputToBn(chainDecimals: number, input: string, isSigned = false): BN {
export function inputToBigInt(chainDecimals: number, input: string, isSigned = false) {
const isDecimalValue = input.match(/^(\d+)\.(\d+)$/)
let result

if (isDecimalValue) {
const div = new BN(input.replace(/\.\d*$/, ''))
const div = BigInt(input.replace(/\.\d*$/, ''))
const modString = input.replace(/^\d+\./, '').substring(0, chainDecimals)
const mod = new BN(modString)
const mod = BigInt(modString)

result = div
.mul(BN_TEN.pow(new BN(chainDecimals)))
.add(mod.mul(BN_TEN.pow(new BN(chainDecimals - modString.length))))
result =
div * 10n ** BigInt(chainDecimals) + mod * 10n ** BigInt(chainDecimals - modString.length)
} else {
result = new BN(input.replace(/[^\d]/g, ''))
.mul(BN_TEN.pow(new BN(chainDecimals)))
.muln(isSigned && input.startsWith('-') ? -1 : 1)
result =
BigInt(input.replace(/[^\d]/g, '')) *
10n ** BigInt(chainDecimals) *
(isSigned && input.startsWith('-') ? -1n : 1n)
}

return result
Expand Down

0 comments on commit 239dcae

Please sign in to comment.