From 9b6c31bf0d927da94ea2f927169fa5894f4be757 Mon Sep 17 00:00:00 2001 From: Nikhil Ranjan Date: Wed, 21 Dec 2022 15:22:38 +0100 Subject: [PATCH 1/7] Weights V2 support --- packages/page-contracts/src/Codes/Upload.tsx | 2 +- .../page-contracts/src/Contracts/Call.tsx | 49 ++++-- .../page-contracts/src/Contracts/Deploy.tsx | 2 +- .../src/shared/InputMegaGas.tsx | 154 ++++++++++++++---- packages/page-contracts/src/types.ts | 7 + packages/page-contracts/src/useWeight.ts | 64 +++++++- 6 files changed, 223 insertions(+), 55 deletions(-) diff --git a/packages/page-contracts/src/Codes/Upload.tsx b/packages/page-contracts/src/Codes/Upload.tsx index 3671866c3b46..d0bb3fc5d9f5 100644 --- a/packages/page-contracts/src/Codes/Upload.tsx +++ b/packages/page-contracts/src/Codes/Upload.tsx @@ -88,7 +88,7 @@ function Upload ({ onClose }: Props): React.ReactElement { try { contract = code && contractAbi?.constructors[constructorIndex]?.method && value ? code.tx[contractAbi.constructors[constructorIndex].method]({ - gasLimit: weight.weight, + gasLimit: weight.isWeightV2 ? weight.weightV2 : weight.weight, storageDepositLimit: null, value: contractAbi?.constructors[constructorIndex].isPayable ? value : undefined }, ...params) diff --git a/packages/page-contracts/src/Contracts/Call.tsx b/packages/page-contracts/src/Contracts/Call.tsx index 4a59607f8ca6..be5dcd7d9895 100644 --- a/packages/page-contracts/src/Contracts/Call.tsx +++ b/packages/page-contracts/src/Contracts/Call.tsx @@ -4,13 +4,13 @@ import type { SubmittableExtrinsic } from '@polkadot/api/types'; import type { ContractPromise } from '@polkadot/api-contract'; import type { ContractCallOutcome } from '@polkadot/api-contract/types'; -import type { CallResult } from './types.js'; +import type { WeightV2 } from '@polkadot/types/interfaces'; +import type { CallResult } from './types'; import React, { useCallback, useEffect, useState } from 'react'; import { Button, Dropdown, Expander, InputAddress, InputBalance, Modal, styled, Toggle, TxButton } from '@polkadot/react-components'; -import { useAccountId, useDebounce, useFormField, useToggle } from '@polkadot/react-hooks'; -import { convertWeight } from '@polkadot/react-hooks/useWeight'; +import { useAccountId, useApi, useDebounce, useFormField, useToggle } from '@polkadot/react-hooks'; import { Available } from '@polkadot/react-query'; import { BN, BN_ONE, BN_ZERO } from '@polkadot/util'; @@ -33,9 +33,11 @@ const MAX_CALL_WEIGHT = new BN(5_000_000_000_000).isub(BN_ONE); function Call ({ className = '', contract, messageIndex, onCallResult, onChangeMessage, onClose }: Props): React.ReactElement | null { const { t } = useTranslation(); + const { api } = useApi(); const message = contract.abi.messages[messageIndex]; const [accountId, setAccountId] = useAccountId(); const [estimatedWeight, setEstimatedWeight] = useState(null); + const [estimatedWeightV2, setEstimatedWeightV2] = useState(null); const [value, isValueValid, setValue] = useFormField(BN_ZERO); const [outcomes, setOutcomes] = useState([]); const [execTx, setExecTx] = useState | null>(null); @@ -47,14 +49,18 @@ function Call ({ className = '', contract, messageIndex, onCallResult, onChangeM useEffect((): void => { setEstimatedWeight(null); + setEstimatedWeightV2(null); setParams([]); }, [contract, messageIndex]); useEffect((): void => { value && message.isMutating && setExecTx((): SubmittableExtrinsic<'promise'> | null => { try { - return contract.tx[message.method]({ gasLimit: weight.weight, storageDepositLimit: null, value: message.isPayable ? value : 0 }, ...params); - } catch { + return contract.tx[message.method]( + { gasLimit: weight.isWeightV2 ? weight.weightV2 : weight.weight, storageDepositLimit: null, value: message.isPayable ? value : 0 }, + ...params + ); + } catch (error) { return null; } }); @@ -67,13 +73,26 @@ function Call ({ className = '', contract, messageIndex, onCallResult, onChangeM contract .query[message.method](accountId, { gasLimit: -1, storageDepositLimit: null, value: message.isPayable ? dbValue : 0 }, ...dbParams) - .then(({ gasRequired, result }) => setEstimatedWeight( - result.isOk - ? convertWeight(gasRequired).v1Weight - : null - )) - .catch(() => setEstimatedWeight(null)); - }, [accountId, contract, message, dbParams, dbValue]); + .then(({ gasRequired, result }) => { + if (weight.isWeightV2) { + setEstimatedWeightV2( + result.isOk + ? api.registry.createType('WeightV2', gasRequired) + : null + ); + } else { + setEstimatedWeight( + result.isOk + ? gasRequired + : null + ); + } + }) + .catch(() => { + setEstimatedWeight(null); + setEstimatedWeightV2(null); + }); + }, [api, accountId, contract, message, dbParams, dbValue, weight.isWeightV2]); const _onSubmitRpc = useCallback( (): void => { @@ -82,7 +101,11 @@ function Call ({ className = '', contract, messageIndex, onCallResult, onChangeM } contract - .query[message.method](accountId, { gasLimit: weight.isEmpty ? -1 : weight.weight, storageDepositLimit: null, value: message.isPayable ? value : 0 }, ...params) + .query[message.method]( + accountId, + { gasLimit: weight.isWeightV2 ? weight.weightV2 : weight.isEmpty ? -1 : weight.weight, storageDepositLimit: null, value: message.isPayable ? value : 0 }, + ...params + ) .then((result): void => { setOutcomes([{ ...result, diff --git a/packages/page-contracts/src/Contracts/Deploy.tsx b/packages/page-contracts/src/Contracts/Deploy.tsx index 8a36fd248c2f..9399a9a1ddef 100644 --- a/packages/page-contracts/src/Contracts/Deploy.tsx +++ b/packages/page-contracts/src/Contracts/Deploy.tsx @@ -79,7 +79,7 @@ function Deploy ({ codeHash, constructorIndex = 0, onClose, setConstructorIndex if (blueprint && contractAbi?.constructors[constructorIndex]?.method) { try { return blueprint.tx[contractAbi.constructors[constructorIndex].method]({ - gasLimit: weight.weight, + gasLimit: weight.isWeightV2 ? weight.weightV2 : weight.weight, salt: withSalt ? salt : null, diff --git a/packages/page-contracts/src/shared/InputMegaGas.tsx b/packages/page-contracts/src/shared/InputMegaGas.tsx index c6700ba3b801..76f593851469 100644 --- a/packages/page-contracts/src/shared/InputMegaGas.tsx +++ b/packages/page-contracts/src/shared/InputMegaGas.tsx @@ -1,24 +1,42 @@ // Copyright 2017-2023 @polkadot/app-contracts authors & contributors // SPDX-License-Identifier: Apache-2.0 +import type { WeightV2 } from '@polkadot/types/interfaces'; import type { BN } from '@polkadot/util'; import type { UseWeight } from '../types.js'; import React, { useEffect, useMemo, useState } from 'react'; -import { InputNumber, styled, Toggle } from '@polkadot/react-components'; +import { InputNumber, Toggle } from '@polkadot/react-components'; import { BN_MILLION, BN_ONE, BN_ZERO } from '@polkadot/util'; import { useTranslation } from '../translate.js'; interface Props { className?: string; - estimatedWeight?: BN | null; + estimatedWeight?: BN + estimatedWeightV2?: WeightV2; + help: React.ReactNode; isCall?: boolean; weight: UseWeight; } -function InputMegaGas ({ className, estimatedWeight, isCall, weight: { executionTime, isValid, megaGas, percentage, setIsEmpty, setMegaGas } }: Props): React.ReactElement { +function InputMegaGas ({ className, + estimatedWeight, + estimatedWeightV2, + help, + isCall, + weight: { executionTime, + isValid, + isWeightV2, + megaGas, + megaRefTime, + percentage, + proofSize, + setIsEmpty, + setMegaGas, + setMegaRefTime, + setProofSize } }: Props): React.ReactElement { const { t } = useTranslation(); const [withEstimate, setWithEstimate] = useState(true); @@ -29,10 +47,32 @@ function InputMegaGas ({ className, estimatedWeight, isCall, weight: { execution [estimatedWeight] ); + const estimatedMgRefTime = useMemo( + () => estimatedWeightV2 + ? estimatedWeightV2.refTime.toBn().div(BN_MILLION).iadd(BN_ONE) + : null, + [estimatedWeightV2] + ); + + const estimatedProofSize = useMemo( + () => estimatedWeightV2 + ? estimatedWeightV2.proofSize.toBn() + : null, + [estimatedWeightV2] + ); + useEffect((): void => { withEstimate && estimatedMg && setMegaGas(estimatedMg); }, [estimatedMg, setMegaGas, withEstimate]); + useEffect((): void => { + withEstimate && estimatedMgRefTime && setMegaRefTime(estimatedMgRefTime); + }, [estimatedMgRefTime, setMegaRefTime, withEstimate]); + + useEffect((): void => { + withEstimate && estimatedProofSize && setProofSize(estimatedProofSize); + }, [estimatedProofSize, setProofSize, withEstimate]); + useEffect((): void => { setIsEmpty(withEstimate && !!isCall); }, [isCall, setIsEmpty, withEstimate]); @@ -40,43 +80,85 @@ function InputMegaGas ({ className, estimatedWeight, isCall, weight: { execution const isDisabled = !!estimatedMg && withEstimate; return ( - - ('max gas allowed (M, {{estimatedMg}} estimated)', { replace: { estimatedMg: estimatedMg.toString() } }) - : t('max gas allowed (M)') - } - labelExtra={(estimatedWeight || isCall) && ( - + {isWeightV2 + ? <> + ('max RefTime allowed (M, {{estimatedRefTime}} estimated)', { replace: { estimatedMgRefTime: estimatedMgRefTime.toString() } }) + : t('max RefTime allowed (M)') + } + onChange={isDisabled ? undefined : setMegaRefTime} + value={isDisabled ? undefined : ((isCall && withEstimate) ? BN_ZERO : megaRefTime)} + > + {(estimatedWeightV2 || isCall) && ( + ('max read gas') + : t('use estimated gas') + } + onChange={setWithEstimate} + value={withEstimate} + /> + )} + + ('max read gas') - : t('use estimated gas') + estimatedProofSize && (isCall ? !withEstimate : true) + ? t('max ProofSize allowed ({{estimatedProofSize}} estimated)', { replace: { estimatedProofSize: estimatedProofSize.toString() } }) + : t('max ProofSize allowed') } - onChange={setWithEstimate} - value={withEstimate} + onChange={isDisabled ? undefined : setProofSize} + value={isDisabled ? undefined : ((isCall && withEstimate) ? BN_ZERO : proofSize)} /> - )} - onChange={isDisabled ? undefined : setMegaGas} - value={isDisabled ? undefined : ((isCall && withEstimate) ? BN_ZERO : megaGas)} - /> -
- {t('{{executionTime}}s execution time', { replace: { executionTime: executionTime.toFixed(3) } })}{', '} - {t('{{percentage}}% of block weight', { replace: { percentage: percentage.toFixed(2) } })} -
-
+
+ {t('{{executionTime}}s execution time', { replace: { executionTime: executionTime.toFixed(3) } })}{', '} + {t('{{percentage}}% of block weight', { replace: { percentage: percentage.toFixed(2) } })} +
+ + : <> + ('max gas allowed (M, {{estimatedMg}} estimated)', { replace: { estimatedMg: estimatedMg.toString() } }) + : t('max gas allowed (M)') + } + onChange={isDisabled ? undefined : setMegaGas} + value={isDisabled ? undefined : ((isCall && withEstimate) ? BN_ZERO : megaGas)} + > + {(estimatedWeight || isCall) && ( + ('max read gas') + : t('use estimated gas') + } + onChange={setWithEstimate} + value={withEstimate} + /> + )} + +
+ {t('{{executionTime}}s execution time', { replace: { executionTime: executionTime.toFixed(3) } })}{', '} + {t('{{percentage}}% of block weight', { replace: { percentage: percentage.toFixed(2) } })} +
+ } + ); } -const StyledDiv = styled.div` - .contracts--InputMegaGas-meter { - text-align: right; - } -`; - export default React.memo(InputMegaGas); diff --git a/packages/page-contracts/src/types.ts b/packages/page-contracts/src/types.ts index 1b41ba8675a5..5f0f72a4d8c6 100644 --- a/packages/page-contracts/src/types.ts +++ b/packages/page-contracts/src/types.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { Abi } from '@polkadot/api-contract'; +import type { WeightV2 } from '@polkadot/types/interfaces'; import type { BN } from '@polkadot/util'; export interface CodeJson { @@ -29,9 +30,15 @@ export interface UseWeight { executionTime: number; isEmpty: boolean; isValid: boolean; + isWeightV2: boolean; megaGas: BN; + megaRefTime: BN; + proofSize: BN; percentage: number; setIsEmpty: React.Dispatch setMegaGas: React.Dispatch; + setMegaRefTime: React.Dispatch; + setProofSize: React.Dispatch; weight: BN; + weightV2: WeightV2; } diff --git a/packages/page-contracts/src/useWeight.ts b/packages/page-contracts/src/useWeight.ts index bf0d19b983e8..5245cc3224d1 100644 --- a/packages/page-contracts/src/useWeight.ts +++ b/packages/page-contracts/src/useWeight.ts @@ -1,7 +1,7 @@ // Copyright 2017-2023 @polkadot/react-hooks authors & contributors // SPDX-License-Identifier: Apache-2.0 -import type { Weight } from '@polkadot/types/interfaces'; +import type { Weight, WeightV2 } from '@polkadot/types/interfaces'; import type { BN } from '@polkadot/util'; import type { UseWeight } from './types.js'; @@ -9,11 +9,12 @@ import { useCallback, useMemo, useState } from 'react'; import { createNamedHook, useApi, useBlockInterval } from '@polkadot/react-hooks'; import { convertWeight } from '@polkadot/react-hooks/useWeight'; -import { BN_MILLION, BN_TEN, BN_ZERO } from '@polkadot/util'; +import { BN_MILLION, BN_ONE, BN_TEN, BN_ZERO } from '@polkadot/util'; function useWeightImpl (): UseWeight { const { api } = useApi(); const blockTime = useBlockInterval(); + const isWeightV2 = !!api.registry.createType('Weight').proofSize; const [megaGas, _setMegaGas] = useState( convertWeight( api.consts.system.blockWeights @@ -21,6 +22,16 @@ function useWeightImpl (): UseWeight { : api.consts.system.maximumBlockWeight as Weight ).v1Weight.div(BN_MILLION).div(BN_TEN) ); + const [megaRefTime, _setMegaRefTime] = useState( + api.consts.system.blockWeights + ? api.consts.system.blockWeights.perClass.normal.maxExtrinsic.unwrapOrDefault().refTime.toBn().div(BN_MILLION).div(BN_TEN) + : BN_ZERO + ); + const [proofSize, _setProofSize] = useState( + api.consts.system.blockWeights + ? api.consts.system.blockWeights.perClass.normal.maxExtrinsic.unwrapOrDefault().proofSize.toBn() + : BN_ZERO + ); const [isEmpty, setIsEmpty] = useState(false); const setMegaGas = useCallback( @@ -32,11 +43,33 @@ function useWeightImpl (): UseWeight { ).v1Weight.div(BN_MILLION).div(BN_TEN)), [api] ); + const setMegaRefTime = useCallback( + (value?: BN | undefined) => + _setMegaRefTime( + value || api.consts.system.blockWeights + ? api.consts.system.blockWeights.perClass.normal.maxExtrinsic.unwrapOrDefault().refTime.toBn().div(BN_MILLION).div(BN_TEN) + : BN_ZERO + ), + [api] + ); + const setProofSize = useCallback( + (value?: BN | undefined) => + _setProofSize( + value || api.consts.system.blockWeights + ? api.consts.system.blockWeights.perClass.normal.maxExtrinsic.unwrapOrDefault().proofSize.toBn() + : BN_ZERO + ), + [api] + ); return useMemo((): UseWeight => { let executionTime = 0; let percentage = 0; let weight = BN_ZERO; + let weightV2 = api.registry.createType('WeightV2', { + proofSize: BN_ZERO, + refTime: BN_ZERO + }); let isValid = false; if (megaGas) { @@ -53,17 +86,40 @@ function useWeightImpl (): UseWeight { isValid = !megaGas.isZero() && percentage < 65; } + if (isWeightV2 && megaRefTime && proofSize) { + weightV2 = api.registry.createType('WeightV2', { + proofSize, + refTime: megaRefTime.mul(BN_MILLION) + }); + executionTime = megaRefTime.mul(BN_MILLION).mul(blockTime).div( + api.consts.system.blockWeights + ? api.consts.system.blockWeights.perClass.normal.maxExtrinsic.unwrapOrDefault().refTime.toBn() + : BN_ONE + ).toNumber(); + percentage = (executionTime / blockTime.toNumber()) * 100; + + // execution is 2s of 6s blocks, i.e. 1/3 + executionTime = executionTime / 3000; + isValid = !megaRefTime.isZero(); // && percentage < 65; + } + return { executionTime, isEmpty, isValid: isEmpty || isValid, + isWeightV2, megaGas: megaGas || BN_ZERO, + megaRefTime: megaRefTime || BN_ZERO, percentage, + proofSize: proofSize || BN_ZERO, setIsEmpty, setMegaGas, - weight + setMegaRefTime, + setProofSize, + weight, + weightV2 }; - }, [api, blockTime, isEmpty, megaGas, setIsEmpty, setMegaGas]); + }, [api, blockTime, isEmpty, isWeightV2, megaGas, megaRefTime, proofSize, setIsEmpty, setMegaGas, setMegaRefTime, setProofSize]); } export default createNamedHook('useWeight', useWeightImpl); From f45a04c24dd92199688365d29b1d7a80b14f6eb7 Mon Sep 17 00:00:00 2001 From: Nikhil Ranjan Date: Wed, 21 Dec 2022 15:34:39 +0100 Subject: [PATCH 2/7] estimated v2 --- packages/apps/public/locales/en/app-contracts.json | 4 ++++ packages/page-contracts/src/Contracts/Call.tsx | 10 +++++++++- packages/page-contracts/src/shared/InputMegaGas.tsx | 4 ++-- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/apps/public/locales/en/app-contracts.json b/packages/apps/public/locales/en/app-contracts.json index 51f9ed0a0f75..6860c5b804c5 100644 --- a/packages/apps/public/locales/en/app-contracts.json +++ b/packages/apps/public/locales/en/app-contracts.json @@ -52,6 +52,10 @@ "deployment constructor": "deployment constructor", "exec": "exec", "json for either ABI or .contract bundle": "json for either ABI or .contract bundle", + "max ProofSize allowed": "max ProofSize allowed", + "max ProofSize allowed ({{estimatedProofSize}} estimated)": "max ProofSize allowed ({{estimatedProofSize}} estimated)", + "max RefTime allowed (M)": "max RefTime allowed (M)", + "max RefTime allowed (M, {{estimatedRefTime}} estimated)": "max RefTime allowed (M, {{estimatedRefTime}} estimated)", "max gas allowed (M)": "max gas allowed (M)", "max gas allowed (M, {{estimatedMg}} estimated)": "max gas allowed (M, {{estimatedMg}} estimated)", "max read gas": "max read gas", diff --git a/packages/page-contracts/src/Contracts/Call.tsx b/packages/page-contracts/src/Contracts/Call.tsx index be5dcd7d9895..cb7a63559c43 100644 --- a/packages/page-contracts/src/Contracts/Call.tsx +++ b/packages/page-contracts/src/Contracts/Call.tsx @@ -83,7 +83,7 @@ function Call ({ className = '', contract, messageIndex, onCallResult, onChangeM } else { setEstimatedWeight( result.isOk - ? gasRequired + ? gasRequired.refTime.toBn() : null ); } @@ -191,6 +191,14 @@ function Call ({ className = '', contract, messageIndex, onCallResult, onChangeM )} ('The maximum amount of gas to use for this contract call. If the call requires more, it will fail.')} isCall={!message.isMutating} weight={weight} /> diff --git a/packages/page-contracts/src/shared/InputMegaGas.tsx b/packages/page-contracts/src/shared/InputMegaGas.tsx index 76f593851469..ce0b40cb2a61 100644 --- a/packages/page-contracts/src/shared/InputMegaGas.tsx +++ b/packages/page-contracts/src/shared/InputMegaGas.tsx @@ -14,8 +14,8 @@ import { useTranslation } from '../translate.js'; interface Props { className?: string; - estimatedWeight?: BN - estimatedWeightV2?: WeightV2; + estimatedWeight?: BN | null; + estimatedWeightV2?: WeightV2 | null; help: React.ReactNode; isCall?: boolean; weight: UseWeight; From 166aabb9ffc6b784b8c796619962195ade844463 Mon Sep 17 00:00:00 2001 From: Nikhil Ranjan Date: Thu, 2 Mar 2023 14:57:08 +0100 Subject: [PATCH 3/7] instantiate --- packages/page-contracts/src/Codes/Upload.tsx | 49 +++++++++++++------ .../src/shared/InputMegaGas.tsx | 2 - 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/packages/page-contracts/src/Codes/Upload.tsx b/packages/page-contracts/src/Codes/Upload.tsx index d0bb3fc5d9f5..0b336d91d5d7 100644 --- a/packages/page-contracts/src/Codes/Upload.tsx +++ b/packages/page-contracts/src/Codes/Upload.tsx @@ -82,23 +82,42 @@ function Upload ({ onClose }: Props): React.ReactElement { }, [abiName, setName]); useEffect((): void => { - let contract: SubmittableExtrinsic<'promise'> | null = null; - let error: string | null = null; - - try { - contract = code && contractAbi?.constructors[constructorIndex]?.method && value - ? code.tx[contractAbi.constructors[constructorIndex].method]({ - gasLimit: weight.isWeightV2 ? weight.weightV2 : weight.weight, - storageDepositLimit: null, - value: contractAbi?.constructors[constructorIndex].isPayable ? value : undefined - }, ...params) - : null; - } catch (e) { - error = (e as Error).message; + async function dryRun () { + let contract: SubmittableExtrinsic<'promise'> | null = null; + let error: string | null = null; + + try { + if (code && contractAbi?.constructors[constructorIndex]?.method && value && accountId) { + const dryRunParams: Parameters = + [ + accountId, + contractAbi?.constructors[constructorIndex].isPayable + ? api.registry.createType('Balance', value) + : api.registry.createType('Balance', BN_ZERO), + weight.weightV2, + null, + { Upload: wasm }, + contractAbi?.constructors[constructorIndex]?.toU8a(params), + '' + ]; + + const dryRunResult = await api.call.contractsApi.instantiate(...dryRunParams); + + contract = code.tx[contractAbi.constructors[constructorIndex].method]({ + gasLimit: dryRunResult.gasRequired, + storageDepositLimit: dryRunResult.storageDeposit.isCharge ? dryRunResult.storageDeposit.asCharge : null, + value: contractAbi?.constructors[constructorIndex].isPayable ? value : undefined + }, ...params); + } + } catch (e) { + error = (e as Error).message; + } + + setUploadTx(() => [contract, error]); } - setUploadTx(() => [contract, error]); - }, [code, contractAbi, constructorIndex, value, params, weight]); + dryRun().catch((e) => console.error(e)); + }, [accountId, wasm, api, code, contractAbi, constructorIndex, value, params, weight]); const _onAddWasm = useCallback( (wasm: Uint8Array, name: string): void => { diff --git a/packages/page-contracts/src/shared/InputMegaGas.tsx b/packages/page-contracts/src/shared/InputMegaGas.tsx index ce0b40cb2a61..d8eff4d30014 100644 --- a/packages/page-contracts/src/shared/InputMegaGas.tsx +++ b/packages/page-contracts/src/shared/InputMegaGas.tsx @@ -16,7 +16,6 @@ interface Props { className?: string; estimatedWeight?: BN | null; estimatedWeightV2?: WeightV2 | null; - help: React.ReactNode; isCall?: boolean; weight: UseWeight; } @@ -24,7 +23,6 @@ interface Props { function InputMegaGas ({ className, estimatedWeight, estimatedWeightV2, - help, isCall, weight: { executionTime, isValid, From 69bcd9ed85cb43bbd29d29d582451b06ca0fd7d7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Mar 2023 15:11:43 +0100 Subject: [PATCH 4/7] [CI Skip] bump/beta 0.124.2-109-x skip-checks: true --- packages/apps/public/locales/en/app-contracts.json | 1 + packages/page-contracts/src/Contracts/Call.tsx | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/apps/public/locales/en/app-contracts.json b/packages/apps/public/locales/en/app-contracts.json index 6860c5b804c5..240550f7ae60 100644 --- a/packages/apps/public/locales/en/app-contracts.json +++ b/packages/apps/public/locales/en/app-contracts.json @@ -26,6 +26,7 @@ "Save": "Save", "The code is not recognized as being in valid WASM format": "The code is not recognized as being in valid WASM format", "The codeHash is not a valid hex hash": "The codeHash is not a valid hex hash", + "The maximum amount of gas to use for this contract call. If the call requires more, it will fail.": "The maximum amount of gas to use for this contract call. If the call requires more, it will fail.", "The value is not in a valid address format": "The value is not in a valid address format", "This operation does not impact the associated on-chain code or any of its contracts.": "This operation does not impact the associated on-chain code or any of its contracts.", "This operation does not remove the uploaded code WASM and ABI from the chain, nor any deployed contracts. The forget operation only limits your access to the code on this browser.": "This operation does not remove the uploaded code WASM and ABI from the chain, nor any deployed contracts. The forget operation only limits your access to the code on this browser.", diff --git a/packages/page-contracts/src/Contracts/Call.tsx b/packages/page-contracts/src/Contracts/Call.tsx index cb7a63559c43..9e797d44850d 100644 --- a/packages/page-contracts/src/Contracts/Call.tsx +++ b/packages/page-contracts/src/Contracts/Call.tsx @@ -198,7 +198,6 @@ function Call ({ className = '', contract, messageIndex, onCallResult, onChangeM refTIme: MAX_CALL_WEIGHT }) } - help={t('The maximum amount of gas to use for this contract call. If the call requires more, it will fail.')} isCall={!message.isMutating} weight={weight} /> From 76b3de06e517a56017d0536d33fa0e45f5910bdd Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 2 Mar 2023 15:57:27 +0100 Subject: [PATCH 5/7] contract call dry run --- .../page-contracts/src/Contracts/Call.tsx | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/packages/page-contracts/src/Contracts/Call.tsx b/packages/page-contracts/src/Contracts/Call.tsx index 9e797d44850d..c6329086d6d5 100644 --- a/packages/page-contracts/src/Contracts/Call.tsx +++ b/packages/page-contracts/src/Contracts/Call.tsx @@ -54,17 +54,41 @@ function Call ({ className = '', contract, messageIndex, onCallResult, onChangeM }, [contract, messageIndex]); useEffect((): void => { - value && message.isMutating && setExecTx((): SubmittableExtrinsic<'promise'> | null => { - try { - return contract.tx[message.method]( - { gasLimit: weight.isWeightV2 ? weight.weightV2 : weight.weight, storageDepositLimit: null, value: message.isPayable ? value : 0 }, - ...params - ); - } catch (error) { - return null; + async function dryRun () { + if (accountId && value && message.isMutating) { + const dryRunParams: Parameters = + [ + accountId, + contract.address, + message.isPayable + ? api.registry.createType('Balance', value) + : api.registry.createType('Balance', BN_ZERO), + weight.weightV2, + null, + message.toU8a(params) + ]; + + const dryRunResult = await api.call.contractsApi.call(...dryRunParams); + + setExecTx((): SubmittableExtrinsic<'promise'> | null => { + try { + return contract.tx[message.method]( + { + gasLimit: dryRunResult.gasRequired, + storageDepositLimit: dryRunResult.storageDeposit.isCharge ? dryRunResult.storageDeposit.asCharge : null, + value: message.isPayable ? value : 0 + }, + ...params + ); + } catch (error) { + return null; + } + }); } - }); - }, [accountId, contract, message, value, weight, params]); + } + + dryRun().catch((e) => console.error(e)); + }, [api, accountId, contract, message, value, weight, params]); useEffect((): void => { if (!accountId || !message || !dbParams || !dbValue) { From fa99aa9d8b5bab7277a6ece519e0312b445e63d4 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Mar 2023 13:30:34 +0200 Subject: [PATCH 6/7] lint fix --- packages/page-contracts/src/Contracts/Call.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/page-contracts/src/Contracts/Call.tsx b/packages/page-contracts/src/Contracts/Call.tsx index c6329086d6d5..7ec3231ae59d 100644 --- a/packages/page-contracts/src/Contracts/Call.tsx +++ b/packages/page-contracts/src/Contracts/Call.tsx @@ -5,7 +5,7 @@ import type { SubmittableExtrinsic } from '@polkadot/api/types'; import type { ContractPromise } from '@polkadot/api-contract'; import type { ContractCallOutcome } from '@polkadot/api-contract/types'; import type { WeightV2 } from '@polkadot/types/interfaces'; -import type { CallResult } from './types'; +import type { CallResult } from './types.js'; import React, { useCallback, useEffect, useState } from 'react'; @@ -80,7 +80,7 @@ function Call ({ className = '', contract, messageIndex, onCallResult, onChangeM }, ...params ); - } catch (error) { + } catch { return null; } }); From 8c04f7b0f6bda33d707068309c4792b86ee5e30f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 28 Mar 2023 13:35:19 +0200 Subject: [PATCH 7/7] uploading raw wasm type --- packages/page-contracts/src/Codes/Upload.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/page-contracts/src/Codes/Upload.tsx b/packages/page-contracts/src/Codes/Upload.tsx index 0b336d91d5d7..0dbded8290d8 100644 --- a/packages/page-contracts/src/Codes/Upload.tsx +++ b/packages/page-contracts/src/Codes/Upload.tsx @@ -96,7 +96,7 @@ function Upload ({ onClose }: Props): React.ReactElement { : api.registry.createType('Balance', BN_ZERO), weight.weightV2, null, - { Upload: wasm }, + { Upload: api.registry.createType('Raw', wasm) }, contractAbi?.constructors[constructorIndex]?.toU8a(params), '' ];