Skip to content

Commit

Permalink
Misc bug fixes and improvements (#108)
Browse files Browse the repository at this point in the history
* (feat) Can now copy state and init params to clipboard
(fix) Remove spurious debug

* (fix) Fix syntax

* (fix) Fix compilation and syntax

* (fix) Fix the bug induced by the typechecker's last attempt to avoid bugs
  • Loading branch information
rrw-zilliqa authored Feb 14, 2025
1 parent 57e0cd6 commit 442568b
Show file tree
Hide file tree
Showing 9 changed files with 149 additions and 28 deletions.
36 changes: 36 additions & 0 deletions src/components/HighlightedCode.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { faCopy } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { FC, PropsWithChildren } from "react";
import docco from "react-syntax-highlighter/dist/esm/styles/hljs/docco";
import { SyntaxHighlighter } from "../highlight-init.ts";

type HighlightedCodeProps = {
language: string;
content: string;
};

export const HighlightedCode: FC<PropsWithChildren<HighlightedCodeProps>> = ({
language,
content,
}) => {
const handleCopy = () => {
navigator.clipboard.writeText(content ?? "");
};
return (
<div className="relative">
<SyntaxHighlighter language={language} style={docco} showLineNumbers>
{content ?? ""}
</SyntaxHighlighter>
<button
className="absolute top-2 right-2 border bg-skin-button-fill px-2 py-1 text-sm text-skin-button hover:bg-skin-button-hover-fill focus:outline-none"
type="button"
onClick={handleCopy}
title="Copy to clipboard"
>
<FontAwesomeIcon icon={faCopy} />
</button>
</div>
);
};

export default HighlightedCode;
11 changes: 2 additions & 9 deletions src/execution/address/ScillaContract.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Tab } from "@headlessui/react";
import React from "react";
import { HighlightedCode } from "../../components/HighlightedCode";
import SwitchTab from "../../components/SwitchTab";
import { SyntaxHighlighter, docco } from "../../highlight-init";
import { ScillaInitParams } from "./ScillaInitParams";
import { ScillaState } from "./ScillaState";

Expand All @@ -23,14 +23,7 @@ const ScillaContract: React.FC<ContractProps> = ({ address, content }) => {
</Tab.List>
<Tab.Panels>
<Tab.Panel>
<SyntaxHighlighter
className="mt-4 h-full w-full border font-code text-base"
language="scilla"
style={docco}
showLineNumbers
>
{content ?? ""}
</SyntaxHighlighter>
<HighlightedCode language="scilla" content={content ?? ""} />
</Tab.Panel>
<Tab.Panel>
{" "}
Expand Down
26 changes: 25 additions & 1 deletion src/execution/address/ScillaInitParams.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { faCopy } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { FC, useContext } from "react";
import { RuntimeContext } from "../../useRuntime";
import { useSmartContractInit } from "../../useZilliqaHooks";
Expand All @@ -12,6 +14,14 @@ type ScillaInitParamRowProps = {
value: string;
};

const formatJsonValue = (value: any): string => {
if (typeof value == "object") {
return JSON.stringify(value, null, 2);
} else {
return value;
}
};

const ScillaInitParamRow: FC<ScillaInitParamRowProps> = ({
name,
valueType,
Expand All @@ -24,7 +34,7 @@ const ScillaInitParamRow: FC<ScillaInitParamRowProps> = ({
<span className="text-gray-600">{name}</span>
</td>
<td className="col-span-1 text-gray-500">{valueType}</td>
<td className="col-span-8 text-gray-500">{value}</td>
<td className="col-span-8 text-gray-500">{formatJsonValue(value)}</td>
</tr>
</>
);
Expand All @@ -33,6 +43,10 @@ const ScillaInitParamRow: FC<ScillaInitParamRowProps> = ({
export const ScillaInitParams: FC<ScillaInitParamsProps> = ({ address }) => {
const { zilliqa } = useContext(RuntimeContext);
const { data, isLoading } = useSmartContractInit(zilliqa, address);
const handleCopy = () => {
navigator.clipboard.writeText(JSON.stringify(data) ?? "");
};

if (isLoading) {
return (
<div className="mt-6">
Expand All @@ -42,6 +56,16 @@ export const ScillaInitParams: FC<ScillaInitParamsProps> = ({ address }) => {
} else {
return (
<div className="mt-6">
<button
className="absolute hover:bg-skin-button-hover-fill focus:outline-none"
type="button"
onClick={handleCopy}
title="Copy to clipboard"
>
<FontAwesomeIcon icon={faCopy} />
</button>
<div className="h-8"></div>

<table className="w-ful border">
<thead>
<tr className="grid grid-cols-12 gap-x-2 bg-gray-100 py-2 text-left">
Expand Down
22 changes: 21 additions & 1 deletion src/execution/address/ScillaState.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { faCopy } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { FC, useContext, useState } from "react";
import { RuntimeContext } from "../../useRuntime";
import { ContractState, useSmartContractState } from "../../useZilliqaHooks";
Expand Down Expand Up @@ -27,7 +29,11 @@ const ScillaStateParamRow: FC<ScillaStateRowProps> = ({ name, value }) => {
};

const formatJsonValue = (value: any): string => {
return JSON.stringify(value, null, 2);
if (typeof value == "object") {
return JSON.stringify(value, null, 2);
} else {
return value;
}
};

export const ScillaState: FC<ScillaStateProps> = ({
Expand Down Expand Up @@ -65,6 +71,10 @@ export const ScillaState: FC<ScillaStateProps> = ({
return <div className="mt-6"> Loading contract state </div>;
}

const handleCopy = () => {
navigator.clipboard.writeText(JSON.stringify(contractState) ?? "");
};

return (
<div className="mt-6">
<button
Expand All @@ -77,6 +87,16 @@ export const ScillaState: FC<ScillaStateProps> = ({
Refresh
</button>

<div className="inline-block w-16"></div>
<button
className="absolute hover:bg-skin-button-hover-fill focus:outline-none"
type="button"
onClick={handleCopy}
title="Copy to clipboard"
>
<FontAwesomeIcon icon={faCopy} />
</button>

<div className={isLoading ? "opacity-50" : ""}>
<table className="w-ful border">
<thead>
Expand Down
22 changes: 18 additions & 4 deletions src/execution/transaction/decoder/DecodedScillaParamsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,30 @@ const DecodedScillaParamRow: FC<DecodedScillaParamRowProps> = ({
return (
<>
<tr className="grid grid-cols-12 gap-x-2 py-2 hover:bg-gray-100">
<td className="col-span-3 pl-1">
<td className="col-span-3 pl-1 break-words">
<span className="text-gray-600">{name}</span>
</td>
<td className="col-span-1 text-gray-500">{valueType}</td>
<td className="col-span-8 text-gray-500">{value}</td>
<td className="col-span-1 text-gray-500 break-words">{valueType}</td>
<td className="col-span-8 text-gray-500 break-words">{value}</td>
</tr>
</>
);
};

function valueOf(val: any): string {
if (val instanceof Object) {
return JSON.stringify(val);
} else {
if (val === null) {
return "null";
}
if (val === undefined) {
return "undefined";
}
return val.toString();
}
}

const DecodedScillaParamsTable: FC<DecodedScillaParamsTableProps> = ({
params,
}) => {
Expand All @@ -47,7 +61,7 @@ const DecodedScillaParamsTable: FC<DecodedScillaParamsTableProps> = ({
key={val["vname"]}
name={val["vname"]}
valueType={val["type"]}
value={val["value"]}
value={valueOf(val["value"])}
/>
))}
</tbody>
Expand Down
17 changes: 15 additions & 2 deletions src/search/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ export const parseSearch = (q: string): string | undefined => {
// Cleanup
q = q.trim();

console.log(`parseSearch q = ${q}`);
let maybeAddress = q;
let maybeIndex = "";
const sepIndex = q.lastIndexOf(":");
Expand All @@ -260,8 +261,11 @@ export const parseSearch = (q: string): string | undefined => {
maybeIndex = !isNaN(parseInt(afterAddress))
? parseInt(afterAddress).toString()
: "";
console.log(`2 = ${maybeAddress}`);
}

console.log(`3 = ${maybeAddress}`);

// Parse URLs for other block explorers
try {
const url = new URL(q);
Expand All @@ -275,6 +279,7 @@ export const parseSearch = (q: string): string | undefined => {
const validatorMatch = pathname.match(/^\/validator\/(.*)$/);
if (addressMatch) {
maybeAddress = addressMatch[1];
console.log(`maybeAddress from ${pathname} -> ${maybeAddress}`);
// The URL might use a different port number
maybeIndex = "";
} else if (txMatch) {
Expand Down Expand Up @@ -309,18 +314,26 @@ export const parseSearch = (q: string): string | undefined => {
} catch (e) {
console.log(`search: Not a bech32 address`);
}
console.log(`4 = ${maybeAddress}`);

// The type checker is convinced that ethers:isAddress() will never say that a string > 40 characters
// long is not an address. I'm not sure why...
if (!isAddress(maybeAddress)) {
let typeCheckerIsWrong = maybeAddress as string;
if (typeCheckerIsWrong.length > 40) {
// remove any leading 0x
console.log(`typeCheckerIsWrong ${typeCheckerIsWrong}`);
if (typeCheckerIsWrong.startsWith("0x")) {
typeCheckerIsWrong = typeCheckerIsWrong.substr(2);
}
console.log(`rem ${typeCheckerIsWrong} ${typeCheckerIsWrong.length}`);
if (typeCheckerIsWrong.length >= 40) {
try {
maybeAddress =
"0x" +
typeCheckerIsWrong
.substr(typeCheckerIsWrong.length - 40)
.toLowerCase();
console.log(`rem2 ${maybeAddress}`);
} catch (e) {
// Obviously not.
}
Expand All @@ -329,7 +342,7 @@ export const parseSearch = (q: string): string | undefined => {

// Plain address?
if (isAddress(maybeAddress)) {
console.log(`search: maybeAddress ${maybeAddress} is an address ..`);
console.log(`search: maybeAddress ${maybeAddress} is an address XXX ..`);
return `/address/${maybeAddress}${maybeIndex !== "" ? `?nonce=${maybeIndex}` : ""}`;
}

Expand Down
11 changes: 6 additions & 5 deletions src/useERC1967.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,17 @@ export type ERC1967ProxyAttributes = {

export const GetStorageQuery = (
provider: JsonRpcApiProvider,
address: Address,
address: Address | undefined,
slot: string,
) => {
return {
queryKey: ["getStorageAt", address, slot],
queryFn: () => {
return provider.getStorage(address, slot);
if (address === undefined) {
return Promise.resolve(undefined);
} else {
return provider.getStorage(address, slot);
}
},
};
};
Expand All @@ -41,9 +45,6 @@ export const useERC1967ProxyAttributes = (
return addr;
}

if (address === undefined) {
return undefined;
}
const { data: delegateData } = useQuery(
GetStorageQuery(provider, address, DELEGATE_STORAGE_LOCATION),
);
Expand Down
28 changes: 24 additions & 4 deletions src/useResolvedAddresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,31 @@ export const useAddressOrENS = (
setChecksummedAddress(undefined);
}
};
resolveName();
} else {
setENS(false);
setError(true);
setChecksummedAddress(undefined);
// Would it be an address if we lowercased it and removed anything other than the leading 0x and the hex chars?
try {
console.log(`trying with ${addressOrName}`);
// typescript thinks that addressOrName is never here, but it isn't ..
const _unsummedAddress = getAddress(
(addressOrName as string).toLowerCase(),
);
if (isAddress(_unsummedAddress)) {
setENS(false);
setError(false);
setChecksummedAddress(_unsummedAddress);
console.log(
`_unsummed = ${_unsummedAddress} is ${isAddress(_unsummedAddress)}`,
);
} else {
setENS(false);
setError(true);
setChecksummedAddress(undefined);
}
} catch (e) {
setENS(false);
setError(true);
setChecksummedAddress(undefined);
}
}
}, [provider, addressOrName, urlFixer]);

Expand Down
4 changes: 2 additions & 2 deletions src/useZilliqaHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ export const smartContractStateFetcher: Fetcher<
[Zilliqa, string, string]
> = async ([zilliqa, methodName, address]) => {
const contract = zilliqa.contracts.at(address);
const initParams = await contract.getState();
return initParams as any;
const state = await contract.getState();
return state as any;
};

export const useSmartContractState = (
Expand Down

0 comments on commit 442568b

Please sign in to comment.