Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/next-common/components/preImages/desktop.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import useColumns from "next-common/components/styledList/useColumns";
import { SecondaryCard } from "next-common/components/styled/containers/secondaryCard";
import { useState } from "react";
import useOldPreimage from "next-common/hooks/useOldPreimage";
import useOldPreimagePapi from "next-common/hooks/useOldPreimagePapi";
import usePreimage from "next-common/hooks/usePreimage";
import usePreimagePapi from "next-common/hooks/usePreimagePapi";
import useOldPreimage from "next-common/hooks/useOldPreimageNew";
import useOldPreimagePapi from "next-common/hooks/useOldPreimagePapiNew";
import usePreimage from "next-common/hooks/usePreimageNew";
import usePreimagePapi from "next-common/hooks/usePreimagePapiNew";
import { useChainSettings } from "next-common/context/chain";
import { useDispatch, useSelector } from "react-redux";
import {
Expand Down
8 changes: 4 additions & 4 deletions packages/next-common/components/preImages/mobile.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { SecondaryCard } from "next-common/components/styled/containers/secondaryCard";
import React, { useState, useEffect, useRef } from "react";
import usePreimage from "next-common/hooks/usePreimage";
import usePreimagePapi from "next-common/hooks/usePreimagePapi";
import useOldPreimage from "next-common/hooks/useOldPreimage";
import useOldPreimagePapi from "next-common/hooks/useOldPreimagePapi";
import usePreimage from "next-common/hooks/usePreimageNew";
import usePreimagePapi from "next-common/hooks/usePreimagePapiNew";
import useOldPreimage from "next-common/hooks/useOldPreimageNew";
import useOldPreimagePapi from "next-common/hooks/useOldPreimagePapiNew";
import { useChainSettings } from "next-common/context/chain";
import { useDispatch } from "react-redux";
import { incPreImagesTrigger } from "next-common/store/reducers/preImagesSlice";
Expand Down
2 changes: 1 addition & 1 deletion packages/next-common/hooks/common/useSubStorage.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ export default function useSubStorage(

const paramsKey = normalizedParams
.map((p) => {
if (p === null || p === undefined) return "null";
if (isNil(p)) return "null";
if (typeof p === "object") {
try {
return JSON.stringify(p);
Expand Down
4 changes: 2 additions & 2 deletions packages/next-common/hooks/useOldPreimageCommon.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function unwrapMaybeValue(value) {

export function toPreimageLength(value) {
const unwrappedValue = unwrapMaybeValue(value);
if (unwrappedValue === null || unwrappedValue === undefined) {
if (isNil(unwrappedValue)) {
return null;
}

Expand All @@ -116,7 +116,7 @@ export function toPreimageLength(value) {

export function toPreimageCount(value) {
const unwrappedValue = unwrapMaybeValue(value);
if (unwrappedValue === null || unwrappedValue === undefined) {
if (isNil(unwrappedValue)) {
return undefined;
}

Expand Down
127 changes: 127 additions & 0 deletions packages/next-common/hooks/useOldPreimageNew.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { useAsync } from "react-use";
import { useContextApi } from "next-common/context/api";
import { BN_ZERO } from "@polkadot/util";
import { Option } from "@polkadot/types";
import {
buildNoBytesResult,
buildBaseResult,
buildCompletedResult,
buildPreimageForKey,
decodeCallBytes,
extractCallData,
isHashOnlyStorageKey,
parseHashOrBounded,
resolveInlinePreimage,
} from "./usePreimageNewCommon";

const oldPreimageResultCache = new Map();

function parseDeposit(rawDeposit) {
if (!rawDeposit) return undefined;
return { who: rawDeposit[0].toString(), amount: rawDeposit[1] };
}

function parseStatusFor(optStatus) {
const status = optStatus.unwrapOr(null);
if (!status) return { status: null };

if (status.isRequested) {
const req = status.asRequested;
// Older versions: asRequested is an option with no structured fields.
if (req instanceof Option) {
return { status, statusName: "requested" };
}
return {
status,
statusName: "requested",
count: req.count.toNumber(),
deposit: parseDeposit(req.deposit.unwrapOr(null)),
proposalLength: req.len.unwrapOr(BN_ZERO),
};
}

if (status.isUnrequested) {
const unreq = status.asUnrequested;
// Older versions, asUnrequested is an option.
if (unreq instanceof Option) {
return {
status,
statusName: "unrequested",
deposit: parseDeposit(unreq.unwrapOr(null)),
};
}
return {
status,
statusName: "unrequested",
deposit: parseDeposit(unreq.deposit),
proposalLength: unreq.len,
};
}

console.error(`Unhandled PalletPreimageRequestStatus type: ${status.type}`);
return { status };
}

async function fetchOldPreimage(proposalHash, api, hashOnly) {
const base = buildBaseResult(proposalHash, hashOnly, api.registry, null);

if (!api.query.preimage?.statusFor) return base;

const optStatus = await api.query.preimage.statusFor(proposalHash);
const parsedStatus = parseStatusFor(optStatus);
const withStatus = { ...base, ...parsedStatus };

if (!parsedStatus.status) return withStatus;

if (!api.query.preimage?.preimageFor) return withStatus;

const bytesKey = buildPreimageForKey(
proposalHash,
withStatus.proposalLength,
hashOnly,
);
const optBytes = await api.query.preimage.preimageFor(...bytesKey);
const callData = extractCallData(optBytes);

if (!callData) return buildNoBytesResult(withStatus);

const decoded = decodeCallBytes(
callData,
api.registry,
withStatus.proposalLength,
);
return buildCompletedResult(withStatus, decoded);
}

export default function useOldPreimage(hashOrBounded) {
const api = useContextApi();

const { value, loading } = useAsync(async () => {
if (!hashOrBounded || !api) return null;

const { proposalHash, inlineData } = parseHashOrBounded(hashOrBounded, api);
if (!proposalHash) return null;

if (oldPreimageResultCache.has(proposalHash)) {
return oldPreimageResultCache.get(proposalHash);
}

const hashOnly = isHashOnlyStorageKey(api);

const result = inlineData
? resolveInlinePreimage(proposalHash, hashOnly, api, inlineData)
: await fetchOldPreimage(proposalHash, api, hashOnly);

if (result?.isCompleted) {
oldPreimageResultCache.set(proposalHash, result);
}

return result;
}, [hashOrBounded, api]);

const isStatusLoaded = Boolean(api) && !loading;
const isPreimageLoaded =
Boolean(api) && !loading && Boolean(value?.isCompleted);

return [value ?? {}, isStatusLoaded, isPreimageLoaded];
}
111 changes: 111 additions & 0 deletions packages/next-common/hooks/useOldPreimagePapiNew.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import { useAsync } from "react-use";
import { Binary } from "polkadot-api";
import { useContextPapi } from "next-common/context/papi";
import {
fetchPapiPreimageBytes,
decodePreimageWithPapi,
toPreimageCount,
toPreimageLength,
convertPapiDepositTuple,
getPapiStatusName,
} from "./useOldPreimageCommon";
import {
parsePapiHashOrBounded,
buildNoBytesResult,
buildBasePapiResult,
resolveInlinePapiPreimage,
} from "./usePreimageNewCommon";

const oldPapiPreimageResultCache = new Map();

function parsePapiStatusFor(rawStatus) {
if (!rawStatus) return { status: null };

const statusName = getPapiStatusName(rawStatus);
const { type, value = {} } = rawStatus;
const result = { status: rawStatus, statusName };

if (type === "Requested") {
result.count = toPreimageCount(value.count);
result.deposit = convertPapiDepositTuple(value.deposit);
result.proposalLength = toPreimageLength(value.len);
} else if (type === "Unrequested") {
result.deposit = convertPapiDepositTuple(value.deposit);
result.proposalLength = toPreimageLength(value.len);
} else {
console.error(`Unhandled PAPI Preimage.StatusFor type: ${type}`);
}

return result;
}

async function fetchOldPapiPreimage(proposalHash, papi, client) {
const base = buildBasePapiResult(proposalHash, null);

if (!papi.query?.Preimage?.StatusFor) return base;

const rawStatus = await papi.query.Preimage.StatusFor.getValue(
Binary.fromHex(proposalHash),
);

const parsedStatus = parsePapiStatusFor(rawStatus);
const withStatus = { ...base, ...parsedStatus };

if (!parsedStatus.status) return withStatus;

const bytes = await fetchPapiPreimageBytes(
papi,
proposalHash,
withStatus.proposalLength,
);

if (!bytes) return buildNoBytesResult(withStatus);

let decoded;
try {
decoded = await decodePreimageWithPapi(withStatus, bytes, client);
} catch {
// ignore
}

if (!decoded) {
return {
...withStatus,
isCompleted: true,
proposalError: "Unable to decode preimage bytes into a valid Call",
};
}

return decoded;
}

export default function useOldPreimagePapi(hashOrBounded) {
const { api: papi, client } = useContextPapi();

const { value, loading } = useAsync(async () => {
if (!hashOrBounded || !papi || !client) return null;

const { proposalHash, inlineData } = parsePapiHashOrBounded(hashOrBounded);
if (!proposalHash) return null;

if (oldPapiPreimageResultCache.has(proposalHash)) {
return oldPapiPreimageResultCache.get(proposalHash);
}

const result = inlineData
? await resolveInlinePapiPreimage(proposalHash, inlineData, client)
: await fetchOldPapiPreimage(proposalHash, papi, client);

if (result?.isCompleted) {
oldPapiPreimageResultCache.set(proposalHash, result);
}

return result;
}, [hashOrBounded, papi, client]);

const isStatusLoaded = Boolean(papi) && Boolean(client) && !loading;
const isPreimageLoaded =
Boolean(papi) && Boolean(client) && !loading && Boolean(value?.isCompleted);

return [value ?? {}, isStatusLoaded, isPreimageLoaded];
}
Loading
Loading