diff --git a/__test-utils__/mocks/contract.ts b/__test-utils__/mocks/contract.ts index f0a08ac1..0d27fe83 100644 --- a/__test-utils__/mocks/contract.ts +++ b/__test-utils__/mocks/contract.ts @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { jest } from '@jest/globals'; -import { Abi, ContractPromise } from 'types'; +import { Abi, Contract } from 'types'; export const mockAbiFlipper = { constructors: [ @@ -61,4 +61,4 @@ export const mockAbiFlipper = { export const mockContract = { abi: mockAbiFlipper, -} as ContractPromise; +} as Contract; diff --git a/package.json b/package.json index 3fefc0da..2eacc755 100644 --- a/package.json +++ b/package.json @@ -28,13 +28,13 @@ "dependencies": { "@headlessui/react": "^1.4.2", "@heroicons/react": "^1.0.5", - "@polkadot/api": "^6.11.1", - "@polkadot/api-contract": "^6.11.1", + "@polkadot/api": "^6.12.2-4", + "@polkadot/api-contract": "^6.12.2-4", "@polkadot/extension-dapp": "^0.41.2", "@polkadot/keyring": "^8.1.2", "@polkadot/react-identicon": "^0.87.5", - "@polkadot/types": "^6.11.1", - "@polkadot/types-support": "^6.11.1", + "@polkadot/types": "^6.12.2-4", + "@polkadot/types-support": "^6.12.2-4", "@polkadot/ui-keyring": "^0.87.5", "@polkadot/ui-settings": "^0.87.5", "@polkadot/util": "^8.1.2", @@ -46,6 +46,7 @@ "@textile/threaddb": "0.1.0", "assert": "^2.0.0", "bcryptjs": "^2.4.3", + "big.js": "^6.1.1", "moment": "^2.29.1", "nanoid": "^3.1.30", "process": "^0.11.10", @@ -69,6 +70,7 @@ "@testing-library/react-hooks": "^7.0.2", "@testing-library/user-event": "^13.5.0", "@types/bcryptjs": "^2.4.2", + "@types/big.js": "^6.1.2", "@types/faker": "^5.5.9", "@types/jest": "^27.0.3", "@types/mini-css-extract-plugin": "^2.4.0", diff --git a/src/api/contract/call.ts b/src/api/contract/call.ts index 40fa4305..f92cb75b 100644 --- a/src/api/contract/call.ts +++ b/src/api/contract/call.ts @@ -56,6 +56,7 @@ export async function call({ message, payment: value, gasLimit, + storageDepositLimit, sender, argValues, dispatch, @@ -76,7 +77,12 @@ export async function call({ if (message.isMutating || message.isPayable) { const tx = prepareContractTx( contract.tx[message.method], - { gasLimit: gasLimit.addn(1), value: message.isPayable ? value || BN_ZERO : undefined, salt }, + { + gasLimit: gasLimit.addn(1), + storageDepositLimit, + value: message.isPayable ? value || BN_ZERO : undefined, + salt, + }, transformed ); diff --git a/src/api/instantiate/createInstantiateTx.ts b/src/api/instantiate/createInstantiateTx.ts index 137fe0e4..cef6b8b7 100644 --- a/src/api/instantiate/createInstantiateTx.ts +++ b/src/api/instantiate/createInstantiateTx.ts @@ -16,12 +16,14 @@ export function createInstantiateTx( endowment, metadata, salt, + storageDepositLimit, }: InstantiateData ): SubmittableExtrinsic<'promise'> | null { const saltu8a = encodeSalt(salt); const options = { gasLimit, + storageDepositLimit: storageDepositLimit || undefined, salt: saltu8a, value: endowment ? api.registry.createType('Balance', endowment) : undefined, }; diff --git a/src/api/instantiate/getInstanceFromEvents.ts b/src/api/instantiate/getInstanceFromEvents.ts index cfc23efb..79288e32 100644 --- a/src/api/instantiate/getInstanceFromEvents.ts +++ b/src/api/instantiate/getInstanceFromEvents.ts @@ -1,16 +1,16 @@ // Copyright 2021 @paritytech/substrate-contracts-explorer authors & contributors // SPDX-License-Identifier: Apache-2.0 -import { ContractPromise } from '@polkadot/api-contract'; -import type { ApiPromise, Abi, EventRecord } from 'types'; +import { ApiPromise, Abi, Contract, ContractPromise, EventRecord } from 'types'; export const getInstanceFromEvents = ( events: EventRecord[], api: ApiPromise, metadata: Abi -): ContractPromise | undefined => { +): Contract | undefined => { let address; - let contract: ContractPromise | undefined; + let contract: Contract | undefined; + events .filter(({ event }) => api.events.contracts.Instantiated.is(event)) .map( diff --git a/src/api/instantiate/instantiate.ts b/src/api/instantiate/instantiate.ts index 85086c13..d90b974d 100644 --- a/src/api/instantiate/instantiate.ts +++ b/src/api/instantiate/instantiate.ts @@ -3,6 +3,7 @@ import { handleDispatchError } from '../util'; import type { + AnyJson, ApiState, DbState, OnInstantiateSuccess$Code, @@ -25,7 +26,7 @@ export function onInsantiateFromHash( if (accountId && codeHash && contract && (status.isInBlock || status.isFinalized)) { await createContract(db, identity, { - abi: contract.abi.json, + abi: contract.abi.json as AnyJson, address: contract.address.toString(), creator: accountId, blockZeroHash: blockZeroHash || undefined, @@ -56,7 +57,7 @@ export function onInstantiateFromCode( if (accountId && contract && (status.isInBlock || status.isFinalized)) { await createContract(db, identity, { - abi: contract.abi.json, + abi: contract.abi.json as AnyJson, address: contract.address.toString(), blockZeroHash: blockZeroHash || undefined, creator: accountId, diff --git a/src/types/substrate.ts b/src/types/substrate.ts index 3d3384ad..9e8df990 100644 --- a/src/types/substrate.ts +++ b/src/types/substrate.ts @@ -1,8 +1,17 @@ // Copyright 2021 @paritytech/substrate-contracts-explorer authors & contributors // SPDX-License-Identifier: Apache-2.0 +import { Blueprint as BlueprintBase, Contract as ContractBase } from '@polkadot/api-contract/base'; + // types & interfaces -export type { AnyJson, Codec, Registry, RegistryError, TypeDef } from '@polkadot/types/types'; +export type { + AnyJson, + CallFunction, + Codec, + Registry, + RegistryError, + TypeDef, +} from '@polkadot/types/types'; export type { DispatchError, EventRecord, Weight } from '@polkadot/types/interfaces'; export type { KeyringPair } from '@polkadot/keyring/types'; export type { @@ -21,3 +30,6 @@ export { Keyring } from '@polkadot/ui-keyring'; export { Abi, ContractPromise, BlueprintPromise } from '@polkadot/api-contract'; export { BlueprintSubmittableResult, CodeSubmittableResult } from '@polkadot/api-contract/base'; export { ApiPromise, SubmittableResult } from '@polkadot/api'; + +export type Blueprint = BlueprintBase<'promise'>; +export type Contract = ContractBase<'promise'>; diff --git a/src/types/ui/contexts.ts b/src/types/ui/contexts.ts index aec770f5..afe67169 100644 --- a/src/types/ui/contexts.ts +++ b/src/types/ui/contexts.ts @@ -4,10 +4,10 @@ import type { Abi, ApiPromise, - BlueprintPromise, + Blueprint, BlueprintSubmittableResult, CodeSubmittableResult, - ContractPromise, + Contract, Keyring, SubmittableExtrinsic, SubmittableResult, @@ -56,6 +56,7 @@ export interface InstantiateData { name: string; constructorIndex: number; salt?: string; + storageDepositLimit?: BN | null; weight: BN; codeHash?: string; } @@ -65,7 +66,7 @@ export interface InstantiateState { onError: () => void; onFinalize?: (data: Partial) => void; onUnFinalize?: () => void; - onSuccess: (_: ContractPromise, __?: BlueprintPromise | undefined) => void; + onSuccess: (_: Contract, __?: Blueprint | undefined) => void; onInstantiate: OnInstantiateSuccess$Code | OnInstantiateSuccess$Hash; currentStep: number; stepForward?: VoidFn; diff --git a/src/types/ui/contract.ts b/src/types/ui/contract.ts index 2bc498e7..ea0b733c 100644 --- a/src/types/ui/contract.ts +++ b/src/types/ui/contract.ts @@ -2,13 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import BN from 'bn.js'; -import type { - AbiMessage, - AnyJson, - ContractPromise, - KeyringPair, - RegistryError, -} from '../substrate'; +import type { AbiMessage, AnyJson, Contract, KeyringPair, RegistryError } from '../substrate'; export type RawParamValue = unknown | undefined; export type RawParamValueArray = (RawParamValue | RawParamValue[])[]; @@ -19,7 +13,7 @@ export interface RawParam { } export interface ContractDryRunParams { - contract: ContractPromise; + contract: Contract; message: AbiMessage; payment: BN; sender: KeyringPair; @@ -28,6 +22,7 @@ export interface ContractDryRunParams { export interface ContractCallParams extends ContractDryRunParams { gasLimit: BN; + storageDepositLimit?: BN; dispatch: (action: ContractCallAction) => void; } diff --git a/src/ui/components/Transactions.tsx b/src/ui/components/Transactions.tsx index 1e300ee5..b631f949 100644 --- a/src/ui/components/Transactions.tsx +++ b/src/ui/components/Transactions.tsx @@ -4,7 +4,7 @@ import { CheckIcon, ClockIcon, ExclamationCircleIcon, XIcon } from '@heroicons/react/outline'; import React from 'react'; import { Spinner } from './common/Spinner'; -import type { TransactionsState } from 'types'; +import type { CallFunction, TransactionsState } from 'types'; import { classes } from 'ui/util'; type Props = React.HTMLAttributes & TransactionsState; @@ -45,7 +45,9 @@ export function Transactions({ className, dismiss, txs }: Props) { > {icon}
-
{extrinsic.registry.findMetaCall(extrinsic.callIndex).method}
+
+ {(extrinsic.registry.findMetaCall(extrinsic.callIndex) as CallFunction).method} +
{text}
{isComplete && ( diff --git a/src/ui/components/common/Meter.tsx b/src/ui/components/common/Meter.tsx new file mode 100644 index 00000000..a01b3a3d --- /dev/null +++ b/src/ui/components/common/Meter.tsx @@ -0,0 +1,32 @@ +// Copyright 2021 @paritytech/substrate-contracts-explorer authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import React from 'react'; +import { classes } from 'ui/util'; + +interface Props { + percentage: number; + label: React.ReactNode; + accessory?: React.ReactNode; + withAccessory?: boolean; +} + +export function Meter({ accessory, label, percentage, withAccessory }: Props) { + return ( +
+
+ {label} + {withAccessory &&
{accessory}
} +
+
+
+
+
+ ); +} diff --git a/src/ui/components/common/index.ts b/src/ui/components/common/index.ts index 50209877..d075ea0e 100644 --- a/src/ui/components/common/index.ts +++ b/src/ui/components/common/index.ts @@ -5,6 +5,7 @@ export * from './Button'; export * from './Dropdown'; export * from './HeaderButtons'; export * from './Loader'; +export * from './Meter'; export * from './Spinner'; export * from './Switch'; export * from './Tabs'; diff --git a/src/ui/components/contract/Interact.tsx b/src/ui/components/contract/Interact.tsx index 88bd71cf..1cd4e82f 100644 --- a/src/ui/components/contract/Interact.tsx +++ b/src/ui/components/contract/Interact.tsx @@ -13,15 +13,18 @@ import { ResultsOutput } from './ResultsOutput'; import { call, createMessageOptions, dryRun } from 'api'; import { useApi } from 'ui/contexts'; import { contractCallReducer, initialState } from 'ui/reducers'; -import { BN, ContractPromise } from 'types'; +import { BN, Contract } from 'types'; import { useAccountId } from 'ui/hooks/useAccountId'; import { useFormField } from 'ui/hooks/useFormField'; import { useArgValues } from 'ui/hooks/useArgValues'; import { useBalance } from 'ui/hooks/useBalance'; import { useWeight } from 'ui/hooks'; +import { useStorageDepositLimit } from 'ui/hooks/useStorageDepositLimit'; +import { InputStorageDepositLimit } from '../form/InputStorageDepositLimit'; +import { useToggle } from 'ui/hooks/useToggle'; interface Props { - contract: ContractPromise; + contract: Contract; } export const InteractTab = ({ contract }: Props) => { @@ -32,6 +35,7 @@ export const InteractTab = ({ contract }: Props) => { const payment = useBalance(100); const { value: accountId, onChange: setAccountId, ...accountIdValidation } = useAccountId(); const [estimatedWeight, setEstimatedWeight] = useState(null); + const [isUsingStorageDepositLimit, toggleIsUsingStorageDepositLimit] = useToggle(); useEffect(() => { if (state.results.length > 0) { @@ -75,6 +79,7 @@ export const InteractTab = ({ contract }: Props) => { }, [api, accountId, argValues, contract, keyring, message.value, payment.value]); const weight = useWeight(); + const storageDepositLimit = useStorageDepositLimit(accountId); if (!contract) return null; @@ -130,6 +135,22 @@ export const InteractTab = ({ contract }: Props) => { {...weight} /> + + +