diff --git a/e2e/decoder.test.ts b/e2e/decoder.test.ts index 00a17d5c..4c3dec5a 100644 --- a/e2e/decoder.test.ts +++ b/e2e/decoder.test.ts @@ -13,10 +13,10 @@ const TOKENS_ACCOUNTS = describe('decoder', () => { it('decode keys', async () => { - const [storage, key] = await decodeKey(chain.head, SYSTEM_ACCOUNT) - expect(storage.section).eq('system') - expect(storage.method).eq('account') - expect(key.args.map((x) => x.toHuman())).contains('25fqepuLngYL2DK9ApTejNzqPadUUZ9ALYyKWX2jyvEiuZLa') + const { storage, decodedKey } = await decodeKey(chain.head, SYSTEM_ACCOUNT) + expect(storage?.section).eq('system') + expect(storage?.method).eq('account') + expect(decodedKey?.args.map((x) => x.toHuman())).contains('25fqepuLngYL2DK9ApTejNzqPadUUZ9ALYyKWX2jyvEiuZLa') }) it('decode key-value', async () => { diff --git a/src/index.ts b/src/index.ts index e60d710d..1d7c9471 100644 --- a/src/index.ts +++ b/src/index.ts @@ -34,7 +34,6 @@ const defaultOptions = { }, block: { desc: 'Block hash or block number. Default to latest block', - string: true, }, 'wasm-override': { desc: 'Path to wasm override', @@ -144,11 +143,15 @@ yargs(hideBin(process.argv)) }), async (argv) => { const context = await setup(processArgv(argv)) - const [storage, decodedKey] = await decodeKey(context.chain.head, argv.key as HexString) - console.log( - `${storage.section}.${storage.method}`, - decodedKey.args.map((x) => JSON.stringify(x.toHuman())).join(', ') - ) + const { storage, decodedKey } = await decodeKey(context.chain.head, argv.key as HexString) + if (storage && decodedKey) { + console.log( + `${storage.section}.${storage.method}`, + decodedKey.args.map((x) => JSON.stringify(x.toHuman())).join(', ') + ) + } else { + console.log('Unknown') + } process.exit(0) } ) diff --git a/src/utils/decoder.ts b/src/utils/decoder.ts index d73479aa..9c37763d 100644 --- a/src/utils/decoder.ts +++ b/src/utils/decoder.ts @@ -5,7 +5,7 @@ import { StorageEntry } from '@polkadot/types/primitive/types' import { StorageKey } from '@polkadot/types' import { create } from 'jsondiffpatch' import { hexToU8a, u8aToHex } from '@polkadot/util' -import { merge, zipObjectDeep } from 'lodash' +import _ from 'lodash' const diffPatcher = create({ array: { detectMove: false } }) @@ -28,29 +28,57 @@ const getStorageEntry = async (block: Block, key: HexString) => { throw new Error(`Cannot find key ${key}`) } -export const decodeKey = async (block: Block, key: HexString): Promise<[StorageEntry, StorageKey]> => { +export const decodeKey = async ( + block: Block, + key: HexString +): Promise<{ storage?: StorageEntry; decodedKey?: StorageKey }> => { const meta = await block.meta - const storage = await getStorageEntry(block, key) + const storage = await getStorageEntry(block, key).catch(() => undefined) const decodedKey = meta.registry.createType('StorageKey', key) - decodedKey.setMeta(storage.meta) - return [storage, decodedKey] + if (storage) { + decodedKey.setMeta(storage.meta) + return { storage, decodedKey } + } + return {} } export const decodeKeyValue = async (block: Block, key: HexString, value?: HexString | null) => { const meta = await block.meta - const [entry, storageKey] = await decodeKey(block, key) + const { storage, decodedKey } = await decodeKey(block, key) + + if (!storage || !decodedKey) { + return { [key]: value } + } - const decodedValue = meta.registry.createType(storageKey.outputType, hexToU8a(value)) + const decodedValue = meta.registry.createType(decodedKey.outputType, hexToU8a(value)) - return { - [entry.section]: { - [entry.method]: - storageKey.args.length > 0 - ? { - ...zipObjectDeep([storageKey.args.map((x) => x.toString()).join('.')], [decodedValue.toHuman()]), - } - : decodedValue.toHuman(), - }, + switch (decodedKey.args.length) { + case 2: { + return { + [storage.section]: { + [storage.method]: { + [decodedKey.args[0].toString()]: { + [decodedKey.args[1].toString()]: decodedValue.toHuman(), + }, + }, + }, + } + } + case 1: { + return { + [storage.section]: { + [storage.method]: { + [decodedKey.args[0].toString()]: decodedValue.toHuman(), + }, + }, + } + } + default: + return { + [storage.section]: { + [storage.method]: decodedValue.toHuman(), + }, + } } } @@ -61,10 +89,8 @@ export const decodeStorageDiff = async (block: Block, diff: [HexString, HexStrin const oldState = {} const newState = {} for (const [key, value] of diff) { - // ignore keys less than 32 chars long because they're not pallet storage - if (key.length < 66) continue - merge(oldState, await decodeKeyValue(block, key as HexString, (await parent.get(key)) as any)) - merge(newState, await decodeKeyValue(block, key as HexString, value)) + _.merge(oldState, await decodeKeyValue(block, key as HexString, (await parent.get(key)) as any)) + _.merge(newState, await decodeKeyValue(block, key as HexString, value)) } return [oldState, newState, diffPatcher.diff(oldState, newState)] } diff --git a/template/diff.html b/template/diff.html index 3918742a..b175a518 100644 --- a/template/diff.html +++ b/template/diff.html @@ -61,6 +61,11 @@ .unchanged { color: #666; } + .delta { + color: #ccc; + font-size: 12px; + margin: 0 10px; + } @@ -102,6 +107,17 @@ ); } + function renderDelta(value) { + if (/^\d+(,\d+)*$/.test(value[1])) { + const oldValue = parseInt(value[0].replace(/,/g, '')) + const newValue = parseInt(value[1].replace(/,/g, '')) + if (oldValue > 0 && newValue > 0) { + const delta = newValue - oldValue + return ({delta > 0 ? '+' : ''}{delta}) + } + } + } + if (isDelta && Array.isArray(value)) { switch (value.length) { case 0: @@ -131,6 +147,7 @@ 'diffUpdateTo', stringifyAndShrink(value[1]) )} + {renderDelta(value)} ); case 3: @@ -150,7 +167,9 @@ }; function prepareDelta(value) { - if (value && value._t === 'a') { + if (!value) return value; + + if (value._t === 'a') { const res = {}; for (const key in value) { if (key !== '_t') { @@ -165,7 +184,7 @@ } return res; } else { - if (Array.isArray(value) && value.length === 3 && value[0].length > 2 && value[0].slice(0, 2) === '@@') { + if (Array.isArray(value) && value.length === 3 && typeof value[0] === 'string' && value[0].startsWith('@@')) { const [left, right] = value[0].split("@@").filter(x => x.length > 0) const items = right.split("\n").slice(1).filter(x => x.length > 0) const oldValue = items.filter(x => x[0] !== '+').map(x => x.slice(1)).join('') @@ -216,7 +235,7 @@