From 7cd88918e22594929c598d883242373b52897dd3 Mon Sep 17 00:00:00 2001 From: Gabe Rodriguez Date: Wed, 25 Sep 2024 10:39:31 +0200 Subject: [PATCH 1/2] Ack & timeout relay msgs --- .../ui/tx/actions-views/ibc-relay.tsx | 246 +++++++++++++----- 1 file changed, 178 insertions(+), 68 deletions(-) diff --git a/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx b/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx index c911f6e490..6ba7a781d2 100644 --- a/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx +++ b/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx @@ -4,93 +4,119 @@ import { FungibleTokenPacketData, IbcRelay, } from '@penumbra-zone/protobuf/penumbra/core/component/ibc/v1/ibc_pb'; -import { MsgRecvPacket } from '@penumbra-zone/protobuf/ibc/core/channel/v1/tx_pb'; +import { + MsgAcknowledgement, + MsgRecvPacket, + MsgTimeout, + MsgTimeoutOnClose, +} from '@penumbra-zone/protobuf/ibc/core/channel/v1/tx_pb'; import { MsgUpdateClient } from '@penumbra-zone/protobuf/ibc/core/client/v1/tx_pb'; import { UnimplementedView } from './unimplemented-view.tsx'; import { uint8ArrayToBase64 } from '@penumbra-zone/types/base64'; +import { ReactElement } from 'react'; +import { Packet } from '@penumbra-zone/protobuf/ibc/core/channel/v1/channel_pb'; import { getUtcTime } from './isc20-withdrawal.tsx'; -import { useMemo } from 'react'; -// Packet data stored as json string encoded into bytes -const parsePacket = ({ packet }: MsgRecvPacket): FungibleTokenPacketData | undefined => { - if (!packet?.data) { +// Attempt to parse data w/ fallbacks if unknown or failures +const ParsedPacketData = ({ + data, + dataParser, +}: { + data: Uint8Array; + dataParser?: (arg: Uint8Array) => ReactElement; +}) => { + if (!data.length) { return undefined; } + if (!dataParser) { + return Unknown packet data; + } + try { - const dataString = new TextDecoder().decode(packet.data); - return FungibleTokenPacketData.fromJsonString(dataString); + return dataParser(data); } catch (e) { - return undefined; + return Error while parsing data; } }; -const MsgResvComponent = ({ packet }: { packet: MsgRecvPacket }) => { - const packetData = useMemo(() => parsePacket(packet), [packet]); +const PacketRows = ({ + packet, + dataParser, +}: { + packet: Packet; + dataParser?: (arg: Uint8Array) => ReactElement; +}) => { + return ( + <> + + {!!packet.sequence && ( + {Number(packet.sequence)} + )} + {!!packet.sourcePort && ( + {packet.sourcePort} + )} + {!!packet.sourceChannel && ( + {packet.sourceChannel} + )} + {!!packet.destinationPort && ( + {packet.destinationPort} + )} + {!!packet.destinationChannel && ( + + {packet.destinationChannel} + + )} + {!!packet.timeoutHeight?.revisionHeight && ( + + {Number(packet.timeoutHeight.revisionHeight)} + + )} + {!!packet.timeoutHeight?.revisionNumber && ( + + {Number(packet.timeoutHeight.revisionNumber)} + + )} + {!!packet.timeoutTimestamp && ( + + {getUtcTime(packet.timeoutTimestamp)} + + )} + + ); +}; + +// Packet data stored as json string encoded into bytes +const parseRecvPacket = (packetData: Uint8Array) => { + const dataString = new TextDecoder().decode(packetData); + const parsed = FungibleTokenPacketData.fromJsonString(dataString); + return ( + <> + {!!parsed.sender && ( + + {parsed.sender} + + )} + {!!parsed.receiver && ( + + {parsed.receiver} + + )} + {!!parsed.denom && {parsed.denom}} + {!!parsed.amount && {parsed.amount}} + {'memo' in parsed && {parsed.memo}} + + ); +}; +const MsgResvComponent = ({ packet }: { packet: MsgRecvPacket }) => { return ( - {packetData === undefined && ( - Unknown packet data - )} - {!!packetData?.sender && ( - - {packetData.sender} - - )} - {!!packetData?.receiver && ( - - {packetData.receiver} - - )} - {!!packetData?.denom && ( - {packetData.denom} - )} - {!!packetData?.amount && ( - {packetData.amount} - )} - {packetData && 'memo' in packetData && ( - {packetData.memo} - )} - {!!packet.packet?.sequence && ( - {Number(packet.packet.sequence)} - )} - {!!packet.packet?.sourcePort && ( - {packet.packet.sourcePort} - )} - {!!packet.packet?.sourceChannel && ( - - {packet.packet.sourceChannel} - - )} - {!!packet.packet?.destinationPort && ( - - {packet.packet.destinationPort} - - )} - {!!packet.packet?.destinationChannel && ( - - {packet.packet.destinationChannel} - - )} - {!!packet.packet?.timeoutHeight?.revisionHeight && ( - - {Number(packet.packet.timeoutHeight.revisionHeight)} - - )} - {!!packet.packet?.timeoutHeight?.revisionNumber && ( - - {Number(packet.packet.timeoutHeight.revisionNumber)} - - )} - {!!packet.packet?.timeoutTimestamp && ( - - {getUtcTime(packet.packet.timeoutTimestamp)} - - )} + {!!packet.packet && } + {packet.signer} {!!packet.proofHeight?.revisionHeight && ( @@ -127,6 +153,72 @@ const UpdateClientComponent = ({ update }: { update: MsgUpdateClient }) => { ); }; +const MsgTimeoutComponent = ({ timeout }: { timeout: MsgTimeout }) => { + return ( + + {!!timeout.packet && } + {!!timeout.proofHeight?.revisionHeight && ( + + {Number(timeout.proofHeight.revisionHeight)} + + )} + {!!timeout.proofHeight?.revisionNumber && ( + + {Number(timeout.proofHeight.revisionNumber)} + + )} + + {Number(timeout.nextSequenceRecv)} + + {timeout.signer} + + + {uint8ArrayToBase64(timeout.proofUnreceived)} + + + + } + /> + ); +}; + +const MsgAckComponent = ({ ack }: { ack: MsgAcknowledgement }) => { + return ( + + {!!ack.packet && } + {!!ack.proofHeight?.revisionHeight && ( + + {Number(ack.proofHeight.revisionHeight)} + + )} + {!!ack.proofHeight?.revisionNumber && ( + + {Number(ack.proofHeight.revisionNumber)} + + )} + {ack.signer} + + + {uint8ArrayToBase64(ack.acknowledgement)} + + + + + {uint8ArrayToBase64(ack.proofAcked)} + + + + } + /> + ); +}; + export const IbcRelayComponent = ({ value }: { value: IbcRelay }) => { if (value.rawAction?.is(MsgRecvPacket.typeName)) { const packet = new MsgRecvPacket(); @@ -140,5 +232,23 @@ export const IbcRelayComponent = ({ value }: { value: IbcRelay }) => { return ; } + if (value.rawAction?.is(MsgTimeout.typeName)) { + const timeout = new MsgTimeout(); + value.rawAction.unpackTo(timeout); + return ; + } + + if (value.rawAction?.is(MsgTimeoutOnClose.typeName)) { + const timeout = new MsgTimeoutOnClose(); + value.rawAction.unpackTo(timeout); + return ; + } + + if (value.rawAction?.is(MsgAcknowledgement.typeName)) { + const ack = new MsgAcknowledgement(); + value.rawAction.unpackTo(ack); + return ; + } + return ; }; From c40814d2233852ab11d2d2abffab0b77dc294770 Mon Sep 17 00:00:00 2001 From: Gabe Rodriguez Date: Thu, 26 Sep 2024 13:51:46 +0200 Subject: [PATCH 2/2] review updates --- .../ui/tx/actions-views/ibc-relay.tsx | 135 +++++++++--------- 1 file changed, 68 insertions(+), 67 deletions(-) diff --git a/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx b/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx index 6ba7a781d2..d7e371f480 100644 --- a/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx +++ b/packages/ui/components/ui/tx/actions-views/ibc-relay.tsx @@ -16,6 +16,7 @@ import { uint8ArrayToBase64 } from '@penumbra-zone/types/base64'; import { ReactElement } from 'react'; import { Packet } from '@penumbra-zone/protobuf/ibc/core/channel/v1/channel_pb'; import { getUtcTime } from './isc20-withdrawal.tsx'; +import { CircleX } from 'lucide-react'; // Attempt to parse data w/ fallbacks if unknown or failures const ParsedPacketData = ({ @@ -50,23 +51,11 @@ const PacketRows = ({ return ( <> - {!!packet.sequence && ( - {Number(packet.sequence)} - )} - {!!packet.sourcePort && ( - {packet.sourcePort} - )} - {!!packet.sourceChannel && ( - {packet.sourceChannel} - )} - {!!packet.destinationPort && ( - {packet.destinationPort} - )} - {!!packet.destinationChannel && ( - - {packet.destinationChannel} - - )} + {Number(packet.sequence)} + {packet.sourcePort} + {packet.sourceChannel} + {packet.destinationPort} + {packet.destinationChannel} {!!packet.timeoutHeight?.revisionHeight && ( {Number(packet.timeoutHeight.revisionHeight)} @@ -77,34 +66,28 @@ const PacketRows = ({ {Number(packet.timeoutHeight.revisionNumber)} )} - {!!packet.timeoutTimestamp && ( - - {getUtcTime(packet.timeoutTimestamp)} - - )} + + {getUtcTime(packet.timeoutTimestamp)} + ); }; // Packet data stored as json string encoded into bytes -const parseRecvPacket = (packetData: Uint8Array) => { +const parseFungibleTokenData = (packetData: Uint8Array) => { const dataString = new TextDecoder().decode(packetData); const parsed = FungibleTokenPacketData.fromJsonString(dataString); return ( <> - {!!parsed.sender && ( - - {parsed.sender} - - )} - {!!parsed.receiver && ( - - {parsed.receiver} - - )} - {!!parsed.denom && {parsed.denom}} - {!!parsed.amount && {parsed.amount}} - {'memo' in parsed && {parsed.memo}} + + {parsed.sender} + + + {parsed.receiver} + + {parsed.denom} + {parsed.amount} + {parsed.memo} ); }; @@ -115,7 +98,9 @@ const MsgResvComponent = ({ packet }: { packet: MsgRecvPacket }) => { label='IBC Relay: Msg Received' visibleContent={ - {!!packet.packet && } + {!!packet.packet && ( + + )} {packet.signer} {!!packet.proofHeight?.revisionHeight && ( @@ -159,7 +144,9 @@ const MsgTimeoutComponent = ({ timeout }: { timeout: MsgTimeout }) => { label='IBC Relay: Msg Timeout' visibleContent={ - {!!timeout.packet && } + {!!timeout.packet && ( + + )} {!!timeout.proofHeight?.revisionHeight && ( {Number(timeout.proofHeight.revisionHeight)} @@ -191,7 +178,7 @@ const MsgAckComponent = ({ ack }: { ack: MsgAcknowledgement }) => { label='IBC Relay: Msg Acknowledgement' visibleContent={ - {!!ack.packet && } + {!!ack.packet && } {!!ack.proofHeight?.revisionHeight && ( {Number(ack.proofHeight.revisionHeight)} @@ -220,34 +207,48 @@ const MsgAckComponent = ({ ack }: { ack: MsgAcknowledgement }) => { }; export const IbcRelayComponent = ({ value }: { value: IbcRelay }) => { - if (value.rawAction?.is(MsgRecvPacket.typeName)) { - const packet = new MsgRecvPacket(); - value.rawAction.unpackTo(packet); - return ; - } - - if (value.rawAction?.is(MsgUpdateClient.typeName)) { - const update = new MsgUpdateClient(); - value.rawAction.unpackTo(update); - return ; - } - - if (value.rawAction?.is(MsgTimeout.typeName)) { - const timeout = new MsgTimeout(); - value.rawAction.unpackTo(timeout); - return ; - } - - if (value.rawAction?.is(MsgTimeoutOnClose.typeName)) { - const timeout = new MsgTimeoutOnClose(); - value.rawAction.unpackTo(timeout); - return ; - } - - if (value.rawAction?.is(MsgAcknowledgement.typeName)) { - const ack = new MsgAcknowledgement(); - value.rawAction.unpackTo(ack); - return ; + try { + if (value.rawAction?.is(MsgRecvPacket.typeName)) { + const packet = new MsgRecvPacket(); + value.rawAction.unpackTo(packet); + return ; + } + + if (value.rawAction?.is(MsgUpdateClient.typeName)) { + const update = new MsgUpdateClient(); + value.rawAction.unpackTo(update); + return ; + } + + if (value.rawAction?.is(MsgTimeout.typeName)) { + const timeout = new MsgTimeout(); + value.rawAction.unpackTo(timeout); + return ; + } + + if (value.rawAction?.is(MsgTimeoutOnClose.typeName)) { + const timeout = new MsgTimeoutOnClose(); + value.rawAction.unpackTo(timeout); + return ; + } + + if (value.rawAction?.is(MsgAcknowledgement.typeName)) { + const ack = new MsgAcknowledgement(); + value.rawAction.unpackTo(ack); + return ; + } + } catch (e) { + return ( + + + Error while parsing details + + } + /> + ); } return ;