diff --git a/components/icons/ArrowRightIcon.tsx b/components/icons/ArrowRightIcon.tsx index db6aa82d..ac3020b8 100644 --- a/components/icons/ArrowRightIcon.tsx +++ b/components/icons/ArrowRightIcon.tsx @@ -1,10 +1,14 @@ import React from 'react'; import { SVGProps } from 'react'; -export const ArrowRightIcon: React.FC> = props => ( +interface ArrowRightIconProps extends SVGProps { + size?: number; +} + +export const ArrowRightIcon: React.FC = ({ size, ...props }) => ( ); } + +export function objectSyntax(object: Record, theme: string) { + const prettyPrintJSON = (obj: Record): string => { + return JSON.stringify(obj, null, 2); + }; + + return ( + + {prettyPrintJSON(object)} + + ); +} diff --git a/components/react/authSignerModal.tsx b/components/react/authSignerModal.tsx index 7a9eed2e..0a51c2d1 100644 --- a/components/react/authSignerModal.tsx +++ b/components/react/authSignerModal.tsx @@ -1,4 +1,4 @@ -import { useEffect } from 'react'; +import { useEffect, useState } from 'react'; import { SignData } from '@cosmos-kit/web3auth'; import { TxBody, AuthInfo } from '@liftedinit/manifestjs/dist/codegen/cosmos/tx/v1beta1/tx'; import { decodePubkey } from '@cosmjs/proto-signing'; @@ -6,31 +6,149 @@ import { useWallet, useChain } from '@cosmos-kit/react'; import { getRealLogo } from '@/utils'; import { useTheme } from '@/contexts'; import env from '@/config/env'; +import { ArrowRightIcon } from '../icons'; +import { objectSyntax } from '../messageSyntax'; +import { MsgSend } from '@liftedinit/manifestjs/dist/codegen/cosmos/bank/v1beta1/tx'; +import { + MsgCreateGroupWithPolicy, + MsgSubmitProposal, + MsgUpdateGroupMembers, + MsgUpdateGroupPolicyMetadata, + MsgUpdateGroupPolicyDecisionPolicy, + MsgUpdateGroupMetadata, +} from '@liftedinit/manifestjs/dist/codegen/cosmos/group/v1/tx'; +import { + MsgCancelUpgrade, + MsgSoftwareUpgrade, +} from '@liftedinit/manifestjs/dist/codegen/cosmos/upgrade/v1beta1/tx'; +import { MsgSetPower } from '@liftedinit/manifestjs/dist/codegen/strangelove_ventures/poa/v1/tx'; +import { + MsgPayout, + MsgBurnHeldBalance, +} from '@liftedinit/manifestjs/dist/codegen/liftedinit/manifest/v1/tx'; +import { + MsgSetDenomMetadata, + MsgCreateDenom, +} from '@liftedinit/manifestjs/dist/codegen/osmosis/tokenfactory/v1beta1/tx'; type DisplayDataToSignProps = { data: SignData; address: string; }; +// Message decoder registry +const messageDecoders: Record any> = { + '/cosmos.bank.v1beta1.MsgSend': (value: Uint8Array) => { + const decoded = MsgSend.decode(value); + return { ...decoded }; + }, + '/cosmos.group.v1.MsgCreateGroupWithPolicy': (value: Uint8Array) => { + const decoded = MsgCreateGroupWithPolicy.decode(value); + return { ...decoded }; + }, + '/cosmos.group.v1.MsgSubmitProposal': (value: Uint8Array) => { + const decoded = MsgSubmitProposal.decode(value); + return { ...decoded }; + }, + '/cosmos.group.v1.MsgUpdateGroupMetadata': (value: Uint8Array) => { + const decoded = MsgUpdateGroupMetadata.decode(value); + return { ...decoded }; + }, + '/cosmos.group.v1.MsgUpdateGroupPolicyMetadata': (value: Uint8Array) => { + const decoded = MsgUpdateGroupPolicyMetadata.decode(value); + return { ...decoded }; + }, + '/cosmos.group.v1.MsgUpdateGroupPolicyDecisionPolicy': (value: Uint8Array) => { + const decoded = MsgUpdateGroupPolicyDecisionPolicy.decode(value); + return { ...decoded }; + }, + '/cosmos.group.v1.MsgUpdateGroupMembers': (value: Uint8Array) => { + const decoded = MsgUpdateGroupMembers.decode(value); + return { ...decoded }; + }, + '/cosmos.upgrade.v1beta1.MsgCancelUpgrade': (value: Uint8Array) => { + const decoded = MsgCancelUpgrade.decode(value); + return { ...decoded }; + }, + '/cosmos.upgrade.v1beta1.MsgSoftwareUpgrade': (value: Uint8Array) => { + const decoded = MsgSoftwareUpgrade.decode(value); + return { ...decoded }; + }, + '/strangelove_ventures.poa.v1.MsgSetPower': (value: Uint8Array) => { + const decoded = MsgSetPower.decode(value); + return { ...decoded }; + }, + '/liftedinit.manifest.v1.MsgPayout': (value: Uint8Array) => { + const decoded = MsgPayout.decode(value); + return { ...decoded }; + }, + '/liftedinit.manifest.v1.MsgBurnHeldBalance': (value: Uint8Array) => { + const decoded = MsgBurnHeldBalance.decode(value); + return { ...decoded }; + }, + '/osmosis.tokenfactory.v1beta1.MsgSetDenomMetadata': (value: Uint8Array) => { + const decoded = MsgSetDenomMetadata.decode(value); + return { ...decoded }; + }, + '/osmosis.tokenfactory.v1beta1.MsgCreateDenom': (value: Uint8Array) => { + const decoded = MsgCreateDenom.decode(value); + return { ...decoded }; + }, +}; + const DisplayDataToSign = ({ data, address, className, addressClassName, txInfoClassName, + theme, }: DisplayDataToSignProps & { className?: string; addressClassName?: string; txInfoClassName?: string; + theme?: string; }) => { + const [isAddressExpanded, setIsAddressExpanded] = useState(false); + const [isTxInfoExpanded, setIsTxInfoExpanded] = useState(false); + const decodeBodyBytes = (bodyBytes: Uint8Array) => { try { const decodedBody = TxBody.decode(bodyBytes); return { - messages: decodedBody.messages.map(msg => ({ - typeUrl: msg.typeUrl, - value: Buffer.from(msg.value).toString('base64'), - })), + messages: decodedBody.messages.map(msg => { + const base64Value = Buffer.from(msg.value).toString('base64'); + + try { + // Check if we have a specific decoder for this message type + if (messageDecoders[msg.typeUrl]) { + return { + typeUrl: msg.typeUrl, + value: messageDecoders[msg.typeUrl](msg.value), + }; + } + + // Fallback to generic base64 decoding + const decodedValue = Buffer.from(base64Value, 'base64').toString('utf8'); + try { + return { + typeUrl: msg.typeUrl, + value: JSON.parse(decodedValue), + }; + } catch { + return { + typeUrl: msg.typeUrl, + value: decodedValue, + }; + } + } catch (error) { + console.error(`Failed to decode message of type ${msg.typeUrl}:`, error); + return { + typeUrl: msg.typeUrl, + value: base64Value, + }; + } + }), memo: decodedBody.memo, timeoutHeight: decodedBody.timeoutHeight.toString(), extensionOptions: decodedBody.extensionOptions, @@ -64,7 +182,7 @@ const DisplayDataToSign = ({ } }; - const formatValue = (value: any): string => { + const formatValue = (value: any, theme: string) => { if (value instanceof Uint8Array) { return Buffer.from(value).toString('base64'); } @@ -75,16 +193,17 @@ const DisplayDataToSign = ({ bodyBytes: decodeBodyBytes(value.bodyBytes), authInfoBytes: decodeAuthInfoBytes(value.authInfoBytes), }; - return JSON.stringify( - decodedValue, - (_, v) => (typeof v === 'bigint' ? v.toString() : v), - 2 + return objectSyntax( + JSON.parse( + JSON.stringify(decodedValue, (_, v) => (typeof v === 'bigint' ? v.toString() : v)) + ), + theme ); } - return JSON.stringify(value, (_, v) => (typeof v === 'bigint' ? v.toString() : v), 2); - } - if (typeof value === 'bigint') { - return value.toString(); + return objectSyntax( + JSON.parse(JSON.stringify(value, (_, v) => (typeof v === 'bigint' ? v.toString() : v))), + theme + ); } return String(value); }; @@ -92,12 +211,38 @@ const DisplayDataToSign = ({ return (
- Address -
{address}
+ + {isAddressExpanded &&
{address}
}
- Tx Info -
{formatValue(data.value)}
+ + {isTxInfoExpanded && ( +
{formatValue(data.value, theme ?? 'light')}
+ )}
); @@ -153,6 +298,7 @@ const SignModal = ({