From b484947b7916e6e0e9ecd6d78a7e2aced87b3d54 Mon Sep 17 00:00:00 2001 From: Jaco Greeff Date: Thu, 22 Oct 2020 20:21:38 +0200 Subject: [PATCH] Display last blocks for execution (per contract) (#3917) * Display last blocks for execution (per contract) * Bump API with new block subs * linting --- package.json | 6 +- packages/page-contracts/package.json | 2 +- .../page-contracts/src/Contracts/Contract.tsx | 12 +- .../page-contracts/src/Contracts/index.tsx | 41 ++++++- .../page-contracts/src/Contracts/types.ts | 6 + packages/page-contracts/src/Deploy.tsx | 7 +- packages/page-contracts/src/store.ts | 4 +- packages/react-api/package.json | 2 +- packages/react-components/src/Event.tsx | 20 ++-- .../react-components/src/Status/Queue.tsx | 32 +++-- yarn.lock | 112 +++++++++--------- 11 files changed, 157 insertions(+), 87 deletions(-) diff --git a/package.json b/package.json index cc752275ba..96a2ed8fac 100644 --- a/package.json +++ b/package.json @@ -33,11 +33,11 @@ "afterSign": "electron-builder-notarize" }, "resolutions": { - "@polkadot/api": "^2.3.2-7", - "@polkadot/api-contract": "^2.3.2-7", + "@polkadot/api": "^2.3.2-8", + "@polkadot/api-contract": "^2.3.2-8", "@polkadot/keyring": "^3.6.1", "@polkadot/networks": "^3.6.1", - "@polkadot/types": "^2.3.2-7", + "@polkadot/types": "^2.3.2-8", "@polkadot/util": "^3.6.1", "@polkadot/util-crypto": "^3.6.1", "@polkadot/wasm-crypto": "^1.4.1", diff --git a/packages/page-contracts/package.json b/packages/page-contracts/package.json index fa55d261c1..7cb0fe178f 100644 --- a/packages/page-contracts/package.json +++ b/packages/page-contracts/package.json @@ -12,6 +12,6 @@ "license": "Apache-2.0", "dependencies": { "@babel/runtime": "^7.12.1", - "@polkadot/api-contract": "^2.3.2-7" + "@polkadot/api-contract": "^2.3.2-8" } } diff --git a/packages/page-contracts/src/Contracts/Contract.tsx b/packages/page-contracts/src/Contracts/Contract.tsx index d4839b5f43..912931061b 100644 --- a/packages/page-contracts/src/Contracts/Contract.tsx +++ b/packages/page-contracts/src/Contracts/Contract.tsx @@ -4,6 +4,7 @@ import { ContractCallOutcome } from '@polkadot/api-contract/types'; import { ActionStatus } from '@polkadot/react-components/Status/types'; import { BlockNumber, ContractInfo } from '@polkadot/types/interfaces'; +import { ContractLink } from './types'; import React, { useCallback, useEffect, useState } from 'react'; import keyring from '@polkadot/ui-keyring'; @@ -21,6 +22,7 @@ interface Props { className?: string; contract: ContractPromise; index: number; + links?: ContractLink[]; onCall: (contractIndex: number, messaeIndex: number, resultCb: (messageIndex: number, result?: ContractCallOutcome) => void) => void; } @@ -28,7 +30,7 @@ function transformInfo (optInfo: Option): ContractInfo | null { return optInfo.unwrapOr(null); } -function Contract ({ className, contract, index, onCall }: Props): React.ReactElement | null { +function Contract ({ className, contract, index, links, onCall }: Props): React.ReactElement | null { const { t } = useTranslation(); const { api } = useApi(); const bestNumber = useCall(api.derive.chain.bestNumber); @@ -94,6 +96,14 @@ function Contract ({ className, contract, index, onCall }: Props): React.ReactEl withMessages /> + + {links?.map(({ blockHash, blockNumber }, index): React.ReactNode => ( + #{blockNumber} + ))} + { const { t } = useTranslation(); const { api } = useApi(); + const newBlock = useCall(api.derive.chain.subscribeNewBlocks); const [{ contractIndex, messageIndex, onCallResult }, setIndexes] = useState({ contractIndex: 0, messageIndex: 0 }); const [isCallOpen, setIsCallOpen] = useState(false); + const [contractLinks, setContractLinks] = useState>({}); const headerRef = useRef<[string?, string?, number?][]>([ [t('contracts'), 'start'], - [undefined, undefined, 2], + [undefined, undefined, 3], [t('status'), 'start'], [t('projection'), 'media--1100'], [] ]); + useEffect((): void => { + if (newBlock) { + const exts = newBlock.block.extrinsics + .filter(({ method: { method, section } }) => section === 'contracts' && method === 'call') + .map(({ args }): ContractLink | null => { + const contractId = keyringContracts.find((a) => args[0].eq(a)); + + if (!contractId) { + return null; + } + + return { + blockHash: newBlock.blockHash.toHex(), + blockNumber: formatNumber(newBlock.blockNumber), + contractId + }; + }) + .filter((value): value is ContractLink => !!value); + + exts.length && setContractLinks((links): Record => { + exts.forEach((value): void => { + links[value.contractId] = [value].concat(links[value.contractId] || []).slice(0, 3); + }); + + return { ...links }; + }); + } + }, [keyringContracts, newBlock]); + const contracts = useMemo( () => filterContracts(api, keyringContracts), [api, keyringContracts] @@ -81,6 +115,7 @@ function Contracts ({ contracts: keyringContracts }: Props): React.ReactElement< contract={contract} index={index} key={contract.address.toString()} + links={contractLinks[contract.address.toString()]} onCall={_onCall} /> ))} diff --git a/packages/page-contracts/src/Contracts/types.ts b/packages/page-contracts/src/Contracts/types.ts index 164b44decc..b20a55c72c 100644 --- a/packages/page-contracts/src/Contracts/types.ts +++ b/packages/page-contracts/src/Contracts/types.ts @@ -9,3 +9,9 @@ export interface CallResult extends ContractCallOutcome { params: any[]; when: Date; } + +export interface ContractLink { + blockHash: string; + blockNumber: string; + contractId: string; +} diff --git a/packages/page-contracts/src/Deploy.tsx b/packages/page-contracts/src/Deploy.tsx index a06978c295..919149105f 100644 --- a/packages/page-contracts/src/Deploy.tsx +++ b/packages/page-contracts/src/Deploy.tsx @@ -4,7 +4,6 @@ import { SubmittableExtrinsic } from '@polkadot/api/types'; import { BlueprintSubmittableResult } from '@polkadot/api-contract/promise/types'; import { StringOrNull } from '@polkadot/react-components/types'; -import { CodeStored } from './types'; import BN from 'bn.js'; import React, { useCallback, useEffect, useMemo, useState } from 'react'; @@ -41,12 +40,12 @@ function Deploy ({ codeHash, constructorIndex = 0, onClose, setConstructorIndex }, [constructorIndex]); const code = useMemo( - (): CodeStored => store.getCode(codeHash), + () => store.getCode(codeHash), [codeHash] ); - const [name, isNameValid, setName] = useNonEmptyString(code.json.name); - const { contractAbi, errorText, isAbiError, isAbiSupplied, isAbiValid, onChangeAbi, onRemoveAbi } = useAbi([code.json.abi, code.contractAbi], codeHash, true); + const [name, isNameValid, setName] = useNonEmptyString(code && code.json.name); + const { contractAbi, errorText, isAbiError, isAbiSupplied, isAbiValid, onChangeAbi, onRemoveAbi } = useAbi([code && code.json.abi, code && code.contractAbi], codeHash, true); const blueprint = useMemo( () => isAbiValid && codeHash && contractAbi diff --git a/packages/page-contracts/src/store.ts b/packages/page-contracts/src/store.ts index 3b6cb95bc2..7f79dbc0a4 100644 --- a/packages/page-contracts/src/store.ts +++ b/packages/page-contracts/src/store.ts @@ -23,7 +23,7 @@ class Store extends EventEmitter { return Object.values(this.allCode); } - public getCode (codeHash: string): CodeStored { + public getCode (codeHash: string): CodeStored | undefined { return this.allCode[codeHash]; } @@ -36,7 +36,7 @@ class Store extends EventEmitter { ...partial, codeHash: hex, genesisHash: api.genesisHash.toHex(), - whenCreated: existing.json?.whenCreated || Date.now() + whenCreated: existing?.json.whenCreated || Date.now() }; const key = `${KEY_CODE}${json.codeHash}`; diff --git a/packages/react-api/package.json b/packages/react-api/package.json index b6ecc8812d..fb0c16f7d3 100644 --- a/packages/react-api/package.json +++ b/packages/react-api/package.json @@ -31,7 +31,7 @@ "homepage": "https://github.com/polkadot-js/ui/tree/master/packages/ui-reactive#readme", "dependencies": { "@babel/runtime": "^7.12.1", - "@polkadot/api": "^2.3.2-7", + "@polkadot/api": "^2.3.2-8", "@polkadot/extension-dapp": "^0.35.0-beta.30", "rxjs-compat": "^6.6.3" } diff --git a/packages/react-components/src/Event.tsx b/packages/react-components/src/Event.tsx index bfc1f34886..88952770ea 100644 --- a/packages/react-components/src/Event.tsx +++ b/packages/react-components/src/Event.tsx @@ -39,15 +39,21 @@ function EventDisplay ({ children, className = '', value }: Props): React.ReactE if (value.section === 'contracts' && value.method === 'ContractExecution' && value.data.length === 2) { // see if we have info for this contract const [accountId, encoded] = value.data; - const abi = getContractAbi(accountId.toString()); - if (abi) { - const decoded = abi.decodeEvent(encoded.toU8a(true)); + try { + const abi = getContractAbi(accountId.toString()); - return { - ...decoded, - values: decoded.args.map((value) => ({ isValid: true, value })) - }; + if (abi) { + const decoded = abi.decodeEvent(encoded.toU8a(true)); + + return { + ...decoded, + values: decoded.args.map((value) => ({ isValid: true, value })) + }; + } + } catch (error) { + // ABI mismatch? + console.error(error); } } diff --git a/packages/react-components/src/Status/Queue.tsx b/packages/react-components/src/Status/Queue.tsx index 0418b31632..d98bb3b5d5 100644 --- a/packages/react-components/src/Status/Queue.tsx +++ b/packages/react-components/src/Status/Queue.tsx @@ -104,18 +104,32 @@ function extractEvents (result?: SubmittableResult): ActionStatus[] { message, status: 'error' }; - } else if (section === 'contracts' && method === 'ContractExecution' && data.length === 2) { - // see if we have info for this contract - const [accountId, encoded] = data; - const abi = getContractAbi(accountId.toString()); + } else if (section === 'contracts') { + if (method === 'ContractExecution' && data.length === 2) { + // see if we have info for this contract + const [accountId, encoded] = data; - if (abi) { - const decoded = abi.decodeEvent(encoded.toU8a(true)); + try { + const abi = getContractAbi(accountId.toString()); + if (abi) { + const decoded = abi.decodeEvent(encoded.toU8a(true)); + + return { + action: decoded.event.identifier, + message: 'contract event', + status: 'event' + }; + } + } catch (error) { + // ABI mismatch? + console.error(error); + } + } else if (method === 'Evicted') { return { - action: decoded.event.identifier, - message: 'contract event', - status: 'event' + action: `${section}.${method}`, + message: 'contract evicted', + status: 'error' }; } } diff --git a/yarn.lock b/yarn.lock index 945d3b7ecb..d12711d4fc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2099,57 +2099,57 @@ __metadata: languageName: node linkType: hard -"@polkadot/api-contract@npm:^2.3.2-7": - version: 2.3.2-7 - resolution: "@polkadot/api-contract@npm:2.3.2-7" +"@polkadot/api-contract@npm:^2.3.2-8": + version: 2.3.2-8 + resolution: "@polkadot/api-contract@npm:2.3.2-8" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/api": 2.3.2-7 - "@polkadot/rpc-core": 2.3.2-7 - "@polkadot/types": 2.3.2-7 + "@polkadot/api": 2.3.2-8 + "@polkadot/rpc-core": 2.3.2-8 + "@polkadot/types": 2.3.2-8 "@polkadot/util": ^3.6.1 bn.js: ^5.1.3 rxjs: ^6.6.3 - checksum: 90767f748ecd9ce4fd135f021122b93bfec3eee13114947760783f4785d5d63d77e1bf417aa0c1e81e623565ff19efe757dd48302b6278c5ed0e9686853ff13a + checksum: 1c760119cc5e23e31371dfed73a1d74acdfdcc95e297fdd229a4e4064e00cb60d404e69ba524dc956e82de10b949dee61bca061370a07eb588edeb7829d93330 languageName: node linkType: hard -"@polkadot/api-derive@npm:2.3.2-7": - version: 2.3.2-7 - resolution: "@polkadot/api-derive@npm:2.3.2-7" +"@polkadot/api-derive@npm:2.3.2-8": + version: 2.3.2-8 + resolution: "@polkadot/api-derive@npm:2.3.2-8" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/api": 2.3.2-7 - "@polkadot/rpc-core": 2.3.2-7 - "@polkadot/rpc-provider": 2.3.2-7 - "@polkadot/types": 2.3.2-7 + "@polkadot/api": 2.3.2-8 + "@polkadot/rpc-core": 2.3.2-8 + "@polkadot/rpc-provider": 2.3.2-8 + "@polkadot/types": 2.3.2-8 "@polkadot/util": ^3.6.1 "@polkadot/util-crypto": ^3.6.1 bn.js: ^5.1.3 memoizee: ^0.4.14 rxjs: ^6.6.3 - checksum: ea9812922048387214dc68bbf0fe6d630b09580129a2501d6688b199f57063d4d935d4c28994b5bf2dbf26f49b69138655cccfa38f02dbad89a2251fe1d068b9 + checksum: 4880d17c4a9c9b93f31175aa95eec0f108a685f4a7004dc5789bbc9ded91fa89d38fc36ef49f9913e8f202b180ae2ece5953519ccc12e8bf2a08ddffa3c816e8 languageName: node linkType: hard -"@polkadot/api@npm:^2.3.2-7": - version: 2.3.2-7 - resolution: "@polkadot/api@npm:2.3.2-7" +"@polkadot/api@npm:^2.3.2-8": + version: 2.3.2-8 + resolution: "@polkadot/api@npm:2.3.2-8" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/api-derive": 2.3.2-7 + "@polkadot/api-derive": 2.3.2-8 "@polkadot/keyring": ^3.6.1 - "@polkadot/metadata": 2.3.2-7 - "@polkadot/rpc-core": 2.3.2-7 - "@polkadot/rpc-provider": 2.3.2-7 - "@polkadot/types": 2.3.2-7 - "@polkadot/types-known": 2.3.2-7 + "@polkadot/metadata": 2.3.2-8 + "@polkadot/rpc-core": 2.3.2-8 + "@polkadot/rpc-provider": 2.3.2-8 + "@polkadot/types": 2.3.2-8 + "@polkadot/types-known": 2.3.2-8 "@polkadot/util": ^3.6.1 "@polkadot/util-crypto": ^3.6.1 bn.js: ^5.1.3 eventemitter3: ^4.0.7 rxjs: ^6.6.3 - checksum: f169383c41daa781592f5e85bc2ca53f91d3a7c074b8cd99548a9f53265d60399803c7f260017d308ea93bc66647c5a01445be58353a296b476ce2695ba4d301 + checksum: 64b70712ca97170415a7e301900564640e141de5ad209a0489f74738cbfddb8b361c215de78cf6a96a9617702159f3b4ae82c6d37c0b192199444110a1707574 languageName: node linkType: hard @@ -2205,7 +2205,7 @@ __metadata: resolution: "@polkadot/app-contracts@workspace:packages/page-contracts" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/api-contract": ^2.3.2-7 + "@polkadot/api-contract": ^2.3.2-8 languageName: unknown linkType: soft @@ -2586,17 +2586,17 @@ __metadata: languageName: node linkType: hard -"@polkadot/metadata@npm:2.3.2-7": - version: 2.3.2-7 - resolution: "@polkadot/metadata@npm:2.3.2-7" +"@polkadot/metadata@npm:2.3.2-8": + version: 2.3.2-8 + resolution: "@polkadot/metadata@npm:2.3.2-8" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/types": 2.3.2-7 - "@polkadot/types-known": 2.3.2-7 + "@polkadot/types": 2.3.2-8 + "@polkadot/types-known": 2.3.2-8 "@polkadot/util": ^3.6.1 "@polkadot/util-crypto": ^3.6.1 bn.js: ^5.1.3 - checksum: d606dfaa190b0f8d673e315c017cfa69ab3d23492ba71b5d7861703df2b2377d2d9952442f9174f5beb60dd07c25e42056f5bcb7587fb6333f44185e72853413 + checksum: 4cc1b46f76cf0b8bf9028899d7395eb1402e1a8849b309939bcaecd60b56dbd1e87c607465f0664e22f6c5948672002764bfda76113d850a81e21145fe3f8a0e languageName: node linkType: hard @@ -2614,7 +2614,7 @@ __metadata: resolution: "@polkadot/react-api@workspace:packages/react-api" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/api": ^2.3.2-7 + "@polkadot/api": ^2.3.2-8 "@polkadot/extension-dapp": ^0.35.0-beta.30 rxjs-compat: ^6.6.3 languageName: unknown @@ -2744,35 +2744,35 @@ __metadata: languageName: unknown linkType: soft -"@polkadot/rpc-core@npm:2.3.2-7": - version: 2.3.2-7 - resolution: "@polkadot/rpc-core@npm:2.3.2-7" +"@polkadot/rpc-core@npm:2.3.2-8": + version: 2.3.2-8 + resolution: "@polkadot/rpc-core@npm:2.3.2-8" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/metadata": 2.3.2-7 - "@polkadot/rpc-provider": 2.3.2-7 - "@polkadot/types": 2.3.2-7 + "@polkadot/metadata": 2.3.2-8 + "@polkadot/rpc-provider": 2.3.2-8 + "@polkadot/types": 2.3.2-8 "@polkadot/util": ^3.6.1 memoizee: ^0.4.14 rxjs: ^6.6.3 - checksum: 4c7485e75b38cbf20ae50e3ed76bb941672437770c72fef9e169b64d6995b76ff00f780646220606576875787c1093a5c7514d32a34f9cbcb8d73b58664dc603 + checksum: 8a371c5e664c8197557fce137230fc84c3c56ff897b07a32fcaf431596a21548eac7615face2ebfa7e044feb2231ea9925195b91e3ac40cbf6e132ab16cbba03 languageName: node linkType: hard -"@polkadot/rpc-provider@npm:2.3.2-7": - version: 2.3.2-7 - resolution: "@polkadot/rpc-provider@npm:2.3.2-7" +"@polkadot/rpc-provider@npm:2.3.2-8": + version: 2.3.2-8 + resolution: "@polkadot/rpc-provider@npm:2.3.2-8" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/metadata": 2.3.2-7 - "@polkadot/types": 2.3.2-7 + "@polkadot/metadata": 2.3.2-8 + "@polkadot/types": 2.3.2-8 "@polkadot/util": ^3.6.1 "@polkadot/util-crypto": ^3.6.1 "@polkadot/x-fetch": ^0.3.3 "@polkadot/x-ws": ^0.3.3 bn.js: ^5.1.3 eventemitter3: ^4.0.7 - checksum: 30f2fadeabcaa7c110a41a03659be7ec5b349fa4e8fa2871af47ae95a6389badc5ee0dd301a2ff5a8ce3622faef8f81c49692d1484e68d4e0b504d245cbdd459 + checksum: 85f292e880f80fab87eba44c677e750975065c1a11edf37c80de5d011a7022402777bbbc26b32cda7788397ac0a2f00e30da86777734046f16245d4d662ca91e languageName: node linkType: hard @@ -2785,31 +2785,31 @@ __metadata: languageName: node linkType: hard -"@polkadot/types-known@npm:2.3.2-7": - version: 2.3.2-7 - resolution: "@polkadot/types-known@npm:2.3.2-7" +"@polkadot/types-known@npm:2.3.2-8": + version: 2.3.2-8 + resolution: "@polkadot/types-known@npm:2.3.2-8" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/types": 2.3.2-7 + "@polkadot/types": 2.3.2-8 "@polkadot/util": ^3.6.1 bn.js: ^5.1.3 - checksum: 57c8009faf83208ce9c719a0cbee8745c795f46ede6bbd88e3254ad94bd381a9e9ff3eef7723ce449ff554d58e298c8d653c173d233916bf086bfdcf0ff1cc6a + checksum: a5d8541939a8a47d9843949a938fdf96364ce1c719cba751323944a84db06b2317a81add48f5c2f764150539c30b63ac5e01ba1697067a5b756f1c585ef96c76 languageName: node linkType: hard -"@polkadot/types@npm:^2.3.2-7": - version: 2.3.2-7 - resolution: "@polkadot/types@npm:2.3.2-7" +"@polkadot/types@npm:^2.3.2-8": + version: 2.3.2-8 + resolution: "@polkadot/types@npm:2.3.2-8" dependencies: "@babel/runtime": ^7.12.1 - "@polkadot/metadata": 2.3.2-7 + "@polkadot/metadata": 2.3.2-8 "@polkadot/util": ^3.6.1 "@polkadot/util-crypto": ^3.6.1 "@types/bn.js": ^4.11.6 bn.js: ^5.1.3 memoizee: ^0.4.14 rxjs: ^6.6.3 - checksum: ff05ce6a5a9637c63eea6bdec96021916b4450eb34d393f2dde61314b00930c2e1e38c8e3864ce72349f9aaf2fbcba88b79d0f32ac70c3de7447300e75869e06 + checksum: 88ba74991784c8cb818b914e3122cfe0dd0158872dc3dee3401400e9bb8862a93cd35ad93425353475c7188931b7d46340ff272138506f3eb50384224a1402fb languageName: node linkType: hard