diff --git a/packages/page-alliance/package.json b/packages/page-alliance/package.json index 8ab507c980..7bbc977777 100644 --- a/packages/page-alliance/package.json +++ b/packages/page-alliance/package.json @@ -13,7 +13,6 @@ "type": "module", "version": "0.118.2-22-x", "dependencies": { - "@babel/runtime": "^7.18.9", - "multiformats": "^9.7.1" + "@babel/runtime": "^7.18.9" } } diff --git a/packages/page-alliance/src/util.spec.ts b/packages/page-alliance/src/util.spec.ts index cf1fc0e1d2..220601123b 100644 --- a/packages/page-alliance/src/util.spec.ts +++ b/packages/page-alliance/src/util.spec.ts @@ -4,7 +4,7 @@ import { Metadata, TypeRegistry } from '@polkadot/types'; import substrate from '@polkadot/types-support/metadata/static-substrate'; -import { createIpfsHash, createPalletCid } from './util'; +import { createCid, createPalletCid } from './util'; const registry = new TypeRegistry(); const metadata = new Metadata(registry, substrate); @@ -29,17 +29,17 @@ describe('util', (): void => { describe('createIpfsHash', (): void => { it('encodes a pallet CID into an ipfs hash', (): void => { + const cid = registry.createType('PalletAllianceCid', { + codec: 0x70, + hash_: { + code: 0x12, + digest: '0x5360ecbd380c10f43bc0a6aba27556580011a5e833592df8dcf330c94759e862' + }, + version: 'V0' + }); + expect( - createIpfsHash( - registry.createType('PalletAllianceCid', { - codec: 0x70, - hash_: { - code: 0x12, - digest: '0x5360ecbd380c10f43bc0a6aba27556580011a5e833592df8dcf330c94759e862' - }, - version: 'V0' - }) - ) + createCid(cid).ipfs ).toEqual('QmTx8GZrQGwQ1ZLquZ4yPqSukDdkvKwpYCULsfLo6G47TX'); }); }); diff --git a/packages/page-alliance/src/util.ts b/packages/page-alliance/src/util.ts index 3f75e04d48..f5e193f66d 100644 --- a/packages/page-alliance/src/util.ts +++ b/packages/page-alliance/src/util.ts @@ -5,58 +5,18 @@ import type { PalletAllianceCid } from '@polkadot/types/lookup'; import type { Registry } from '@polkadot/types/types'; import type { Cid } from './types'; -import { CID, digest, varint } from 'multiformats'; - -import { u8aToHex } from '@polkadot/util'; - -export function createIpfsHash (cid: PalletAllianceCid): string | null { - try { - const { codec, hash_: { code, digest: _bytes }, version } = cid; - - // Since we use parse, encode into a fully-specified bytes to - // pass - + + bytes - const bytes = _bytes.toU8a(true); - const codeLen = varint.encodingLength(code.toNumber()); - const sizeLen = varint.encodingLength(bytes.length); - const encoded = new Uint8Array(codeLen + sizeLen + bytes.length); - - varint.encodeTo(code.toNumber(), encoded, 0); - varint.encodeTo(bytes.length, encoded, codeLen); - encoded.set(bytes, codeLen + sizeLen); - - return CID - .create(version.index as 0, codec.toNumber(), digest.decode(encoded)) - .toString(); - } catch (error) { - console.error(`createIpfs: ${(error as Error).message}::`, cid.toHuman()); - - return null; - } -} +import { fromIpfsCid, toIpfsCid } from '@polkadot/react-params/util'; export function createPalletCid (registry: Registry, cid: string): PalletAllianceCid | null { - try { - const { code: codec, multihash: { code, digest }, version } = CID.parse(cid); + const expanded = fromIpfsCid(cid); - return registry.createType('PalletAllianceCid', { - codec, - hash: { - code, - digest: u8aToHex(digest) - }, - version - }); - } catch (error) { - console.error(`encodeCid: ${(error as Error).message}::`, cid); - - return null; - } + return expanded && registry.createType('PalletAllianceCid', expanded); } export function createCid (cid: PalletAllianceCid): Cid { return { cid, - ipfs: createIpfsHash(cid), + ipfs: toIpfsCid(cid), key: cid.toHex() }; } diff --git a/packages/react-params/package.json b/packages/react-params/package.json index 3a87cde8c1..4b839716d5 100644 --- a/packages/react-params/package.json +++ b/packages/react-params/package.json @@ -14,6 +14,7 @@ "version": "0.118.2-22-x", "dependencies": { "@babel/runtime": "^7.18.9", - "@polkadot/react-components": "^0.118.2-22-x" + "@polkadot/react-components": "^0.118.2-22-x", + "multiformats": "^9.7.1" } } diff --git a/packages/react-params/src/Param/Cid.tsx b/packages/react-params/src/Param/Cid.tsx new file mode 100644 index 0000000000..732cf2d7f1 --- /dev/null +++ b/packages/react-params/src/Param/Cid.tsx @@ -0,0 +1,54 @@ +// Copyright 2017-2022 @polkadot/react-params authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { Props } from '../types'; + +import React, { useCallback, useState } from 'react'; + +import { Input } from '@polkadot/react-components'; +import { isCodec } from '@polkadot/util'; + +import { fromIpfsCid } from '../util'; +import Bare from './Bare'; +import Struct from './Struct'; + +function Cid (props: Props): React.ReactElement { + const { className = '', defaultValue, isDisabled, isError, label, onChange, withLabel } = props; + const [isValid, setIsValid] = useState(false); + const [isStruct] = useState(() => isDisabled || !defaultValue || isCodec(defaultValue.value)); + + const _onChange = useCallback( + (_value: string): void => { + const value = fromIpfsCid(_value); + const isValid = !!value; + + onChange && onChange({ + isValid, + value + }); + setIsValid(isValid); + }, + [onChange] + ); + + if (isStruct) { + return ; + } + + return ( + + + + ); +} + +export default React.memo(Cid); diff --git a/packages/react-params/src/Param/findComponent.ts b/packages/react-params/src/Param/findComponent.ts index 82a272ebd5..df3549a1b5 100644 --- a/packages/react-params/src/Param/findComponent.ts +++ b/packages/react-params/src/Param/findComponent.ts @@ -14,6 +14,7 @@ import Balance from './Balance'; import Bool from './Bool'; import Bytes from './Bytes'; import Call from './Call'; +import Cid from './Cid'; import Code from './Code'; import DispatchError from './DispatchError'; import DispatchResult from './DispatchResult'; @@ -53,6 +54,7 @@ const componentDef: TypeToComponent[] = [ { c: Bool, t: ['bool'] }, { c: Bytes, t: ['Bytes', 'Vec'] }, { c: Call, t: ['Call', 'Proposal'] }, + { c: Cid, t: ['PalletAllianceCid'] }, { c: Code, t: ['Code'] }, { c: DispatchError, t: DISPATCH_ERROR }, { c: DispatchResult, t: ['DispatchResult', 'Result'] }, diff --git a/packages/react-params/src/types.ts b/packages/react-params/src/types.ts index cb27f87b98..46f98ba869 100644 --- a/packages/react-params/src/types.ts +++ b/packages/react-params/src/types.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import type { Registry, TypeDef } from '@polkadot/types/types'; +import type { HexString } from '@polkadot/util/types'; // FIXME Ideally, we want these as Base from api-codec - as a stop-gap, any this until we have // params returning types extending Base (i.e. anything from api-codec) @@ -56,3 +57,12 @@ export interface ParamDef { name?: string; type: TypeDef; } + +export interface ExpandedCid { + codec: number; + hash: { + code: number; + digest: HexString; + }; + version: 0 | 1; +} diff --git a/packages/react-params/src/util.ts b/packages/react-params/src/util.ts new file mode 100644 index 0000000000..fa06fa407b --- /dev/null +++ b/packages/react-params/src/util.ts @@ -0,0 +1,53 @@ +// Copyright 2017-2022 @polkadot/react-params authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import type { PalletAllianceCid } from '@polkadot/types/lookup'; +import type { ExpandedCid } from './types'; + +import { CID, digest, varint } from 'multiformats'; + +import { u8aToHex } from '@polkadot/util'; + +export function fromIpfsCid (cid: string): ExpandedCid | null { + try { + const { code: codec, multihash: { code, digest }, version } = CID.parse(cid); + + return { + codec, + hash: { + code, + digest: u8aToHex(digest) + }, + version + }; + } catch (error) { + console.error(`fromIpfsCid: ${(error as Error).message}::`, cid); + + return null; + } +} + +export function toIpfsCid (cid: PalletAllianceCid): string | null { + try { + const { codec, hash_: { code, digest: _bytes }, version } = cid; + + // Since we use parse, encode into a fully-specified bytes to + // pass - + + bytes + const bytes = _bytes.toU8a(true); + const codeLen = varint.encodingLength(code.toNumber()); + const sizeLen = varint.encodingLength(bytes.length); + const encoded = new Uint8Array(codeLen + sizeLen + bytes.length); + + varint.encodeTo(code.toNumber(), encoded, 0); + varint.encodeTo(bytes.length, encoded, codeLen); + encoded.set(bytes, codeLen + sizeLen); + + return CID + .create(version.index as 0, codec.toNumber(), digest.decode(encoded)) + .toString(); + } catch (error) { + console.error(`toIpfsCid: ${(error as Error).message}::`, cid.toHuman()); + + return null; + } +} diff --git a/yarn.lock b/yarn.lock index 97ceaeea19..979a2dec21 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2766,7 +2766,6 @@ __metadata: resolution: "@polkadot/app-alliance@workspace:packages/page-alliance" dependencies: "@babel/runtime": ^7.18.9 - multiformats: ^9.7.1 languageName: unknown linkType: soft @@ -3467,6 +3466,7 @@ __metadata: dependencies: "@babel/runtime": ^7.18.9 "@polkadot/react-components": ^0.118.2-22-x + multiformats: ^9.7.1 languageName: unknown linkType: soft