From e53f18f5e3f9da5a8fb589102eee5f479f9d52b2 Mon Sep 17 00:00:00 2001 From: Rahul Yadav Date: Wed, 21 Aug 2024 13:34:26 +0530 Subject: [PATCH] feat: pretty print getter result --- .../shared/LogView/LogView.module.scss | 3 + src/components/shared/LogView/LogView.tsx | 3 +- src/components/workspace/ABIUi/TactABIUi.tsx | 4 +- src/hooks/contract.hooks.ts | 9 ++- src/utility/utils.ts | 78 ++++++++++++------- 5 files changed, 62 insertions(+), 35 deletions(-) diff --git a/src/components/shared/LogView/LogView.module.scss b/src/components/shared/LogView/LogView.module.scss index af7c42a..f99ef14 100644 --- a/src/components/shared/LogView/LogView.module.scss +++ b/src/components/shared/LogView/LogView.module.scss @@ -14,6 +14,9 @@ display: block; } } + div[class*='xterm-rows'] { + font-size: 17px; + } .tab { display: inline-flex; diff --git a/src/components/shared/LogView/LogView.tsx b/src/components/shared/LogView/LogView.tsx index 388c36f..f55b09c 100644 --- a/src/components/shared/LogView/LogView.tsx +++ b/src/components/shared/LogView/LogView.tsx @@ -108,10 +108,11 @@ const LogView: FC = ({ filter }) => { import('@xterm/addon-search'), ]); _terminal = new Terminal({ - fontSize: 17, + fontSize: 16.5, cursorBlink: false, cursorStyle: 'bar', disableStdin: true, + convertEol: true, }); terminal.current = _terminal; diff --git a/src/components/workspace/ABIUi/TactABIUi.tsx b/src/components/workspace/ABIUi/TactABIUi.tsx index 9234488..d9de623 100644 --- a/src/components/workspace/ABIUi/TactABIUi.tsx +++ b/src/components/workspace/ABIUi/TactABIUi.tsx @@ -375,7 +375,7 @@ const TactABIUi: FC = ({ ); if (Array.isArray(response)) { - createLog(JSON.stringify(response)); + createLog(JSON.stringify(response, null, 2)); } else if (response?.logs) { for (const log of response.logs) { createLog( @@ -384,7 +384,7 @@ const TactABIUi: FC = ({ ); } } else { - createLog(JSON.stringify(response)); + createLog(JSON.stringify(response, null, 2)); } updateABIInputValues( { key: abiType.name, value: formValues, type: type }, diff --git a/src/hooks/contract.hooks.ts b/src/hooks/contract.hooks.ts index dbcbdf4..a63605a 100644 --- a/src/hooks/contract.hooks.ts +++ b/src/hooks/contract.hooks.ts @@ -8,8 +8,9 @@ import { } from '@/interfaces/workspace.interface'; import EventEmitter from '@/utility/eventEmitter'; import { - convertToText, + GetterJSONReponse, tonHttpEndpoint as getHttpEndpoint, + serializeToJSONFormat, } from '@/utility/utils'; import { Network } from '@orbs-network/ton-access'; import { @@ -291,8 +292,8 @@ export function useContractAction() { } type RESPONSE_VALUES = - | { method: string; value: string } - | { type: string; value: string }; + | { method: string; value: string | GetterJSONReponse } + | { type: string; value: string | GetterJSONReponse }; async function callGetter( contractAddress: string, @@ -340,7 +341,7 @@ export function useContractAction() { printDebugLog(); responseValues.push({ method: methodName, - value: convertToText(response), + value: serializeToJSONFormat(response), }); } else { const call = await contract.getData( diff --git a/src/utility/utils.ts b/src/utility/utils.ts index 5930751..8cc910c 100644 --- a/src/utility/utils.ts +++ b/src/utility/utils.ts @@ -131,55 +131,77 @@ export const getFileExtension = (fileName: string) => { }; // eslint-disable-next-line complexity, @typescript-eslint/no-explicit-any -export const convertToText = (obj: any): string => { - //create an array that will later be joined into a string. - const string = []; +export type GetterJSONReponse = + | string + | number + | boolean + | null + | GetterJSONReponse[] + | { [key: string]: GetterJSONReponse }; +/** + * Converts various types of objects, including custom types, arrays, dictionaries, and primitives, into a JSON-compatible format. + * + * This function is particularly useful when dealing with complex data structures that need to be serialized into a JSON format. + * It handles different types, including custom objects like `Address`, `Slice`, `Cell`, and `Dictionary`, converting them into strings. + * Arrays and objects are recursively converted, ensuring that all nested structures are correctly transformed. + * + * @param obj - The object or value to be converted to a JSON-compatible format. It can be of any type. + * @returns A JSON-compatible value (`string`, `number`, `boolean`, `null`, array, or object), or `null` if the input is `undefined` or `null`. + */ +export const serializeToJSONFormat = ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + obj: any, +): GetterJSONReponse | GetterJSONReponse[] | null => { //is object // Both arrays and objects seem to return "object" // when typeof(obj) is applied to them. So instead // I am checking to see if they have the property // join, which normal objects don't have but // arrays do. - if (obj == undefined) { - return String(obj); - } else if (typeof obj == 'object' && obj.join == undefined) { + if (obj === undefined || obj === null) { + return null; + } + + if (typeof obj === 'object' && obj.join === undefined) { if (obj instanceof Address) return obj.toString(); if (obj instanceof Slice) return obj.toString(); if (obj instanceof Cell) return obj.toString(); if (obj instanceof Dictionary) { - const items = []; - for (const key of obj.keys()) - items.push(`${convertToText(key)}: ${convertToText(obj.get(key))}`); - const itemsStr = items.join(', '); - return itemsStr ? `{ ${itemsStr} }` : `{}`; + const resultDict: Record = {}; + for (const key of obj.keys()) { + const jsonKey = serializeToJSONFormat(key); + if (typeof jsonKey === 'string') { + resultDict[jsonKey] = serializeToJSONFormat(obj.get(key)); + } + } + return resultDict; } - for (const prop in obj) { - if (Object.prototype.hasOwnProperty.call(obj, prop)) - string.push(prop + ': ' + convertToText(obj[prop])); + if (Array.isArray(obj)) { + return obj.map((item) => serializeToJSONFormat(item)); } - return '{' + string.join(', ') + '}'; - //is array - } else if (typeof obj == 'object' && !(obj.join == undefined)) { + const resultObj: Record = {}; for (const prop in obj) { - string.push(convertToText(obj[prop])); + if (Object.prototype.hasOwnProperty.call(obj, prop)) { + resultObj[prop] = serializeToJSONFormat( + (obj as Record)[prop], + ); + } } - return '[' + string.join(',') + ']'; + return resultObj; + } - //is function - } else if (typeof obj == 'function') { - string.push(obj.toString()); + if (typeof obj === 'function') { + return obj.toString(); + } - //all other values can be done with JSON.stringify - } else { - if (typeof obj == 'string') string.push(JSON.stringify(obj)); - else if (typeof obj == 'bigint') string.push(obj.toString()); - else string.push(obj.toString()); + if (typeof obj === 'string' || typeof obj === 'bigint') { + return obj.toString(); } - return string.join(','); + return obj as GetterJSONReponse; }; export const tonHttpEndpoint = ({ network }: Config) => {