diff --git a/.changelog/1659.feature.md b/.changelog/1659.feature.md new file mode 100644 index 000000000..fc18ef4f2 --- /dev/null +++ b/.changelog/1659.feature.md @@ -0,0 +1 @@ +Support ROFL transactions diff --git a/src/app/components/CodeDisplay/index.tsx b/src/app/components/CodeDisplay/index.tsx index 34157e2f9..783b8305c 100644 --- a/src/app/components/CodeDisplay/index.tsx +++ b/src/app/components/CodeDisplay/index.tsx @@ -11,11 +11,18 @@ import { base64ToHex } from '../../utils/helpers' type CodeDisplayProps = { code: ReactNode copyToClipboardValue: string - label: string + label?: string extraTopPadding?: boolean + withCopyButton?: boolean } -const CodeDisplay: FC = ({ code, copyToClipboardValue, label, extraTopPadding }) => { +const CodeDisplay: FC = ({ + code, + copyToClipboardValue, + label, + extraTopPadding, + withCopyButton = true, +}) => { const { t } = useTranslation() const { isMobile } = useScreenSize() @@ -34,13 +41,17 @@ const CodeDisplay: FC = ({ code, copyToClipboardValue, label, pt: extraTopPadding ? 4 : 0, }} > - - {label} - - + {label && ( + + {label} + + )} + {withCopyButton && ( + + )} @@ -66,14 +77,16 @@ export const RawDataDisplay: FC = ({ data, label, extraTopP const StyledPre = styled('pre')({ margin: 0, + whiteSpace: 'break-spaces', }) type JsonCodeDisplayProps = { data: Record - label: string + label?: string + withCopyButton?: boolean } -export const JsonCodeDisplay: FC = ({ data, label }) => { +export const JsonCodeDisplay: FC = ({ data, label, withCopyButton = true }) => { const formattedJson = JSON.stringify(data, null, 2) return ( @@ -81,6 +94,7 @@ export const JsonCodeDisplay: FC = ({ data, label }) => { code={{formattedJson}} copyToClipboardValue={formattedJson} label={label} + withCopyButton={withCopyButton} /> ) } diff --git a/src/app/components/RuntimeEvents/RuntimeEventDetails.tsx b/src/app/components/RuntimeEvents/RuntimeEventDetails.tsx index d0358437e..59d1043d6 100644 --- a/src/app/components/RuntimeEvents/RuntimeEventDetails.tsx +++ b/src/app/components/RuntimeEvents/RuntimeEventDetails.tsx @@ -26,6 +26,7 @@ import { MaybeEventErrorLine } from './EventError' import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward' import ArrowForwardIcon from '@mui/icons-material/ArrowForward' import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward' +import MemoryIcon from '@mui/icons-material/Memory' import LanIcon from '@mui/icons-material/Lan' import LanOutlinedIcon from '@mui/icons-material/LanOutlined' import { MethodIcon } from '../ConsensusTransactionMethod' @@ -53,6 +54,12 @@ const getRuntimeEventMethodLabel = (t: TFunction, method: string | undefined) => return t('runtimeEvent.accountsmint') case RuntimeEventType.accountsburn: return t('runtimeEvent.accountsburn') + case RuntimeEventType.roflapp_created: + return t('runtimeEvent.roflAppCreated') + case RuntimeEventType.roflapp_updated: + return t('runtimeEvent.roflAppUpdated') + case RuntimeEventType.roflapp_removed: + return t('runtimeEvent.roflAppRemoved') default: return method || t('common.unknown') } @@ -88,6 +95,9 @@ export const EventTypeIcon: FC<{ [RuntimeEventType.accountsburn]: ( } {...props} /> ), + [RuntimeEventType.roflapp_created]: } {...props} />, + [RuntimeEventType.roflapp_removed]: } {...props} />, + [RuntimeEventType.roflapp_updated]: } {...props} />, } return ( @@ -362,6 +372,19 @@ const RuntimeEventDetailsInner: FC<{ ) + case RuntimeEventType.roflapp_created: + case RuntimeEventType.roflapp_removed: + case RuntimeEventType.roflapp_updated: + return ( +
+ + + +
{t('common.id')}
+
{event.body.id}
+
+
+ ) default: exhaustedTypeWarning('Unexpected event type', event.type) return ( diff --git a/src/app/components/RuntimeTransactionMethod/index.tsx b/src/app/components/RuntimeTransactionMethod/index.tsx index b3a1b22b9..e69909d94 100644 --- a/src/app/components/RuntimeTransactionMethod/index.tsx +++ b/src/app/components/RuntimeTransactionMethod/index.tsx @@ -6,6 +6,7 @@ import FileCopyIcon from '@mui/icons-material/FileCopy' import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward' import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward' import ArrowForwardIcon from '@mui/icons-material/ArrowForward' +import MemoryIcon from '@mui/icons-material/Memory' import QuestionMarkIcon from '@mui/icons-material/QuestionMark' import LanIcon from '@mui/icons-material/Lan' import LanOutlinedIcon from '@mui/icons-material/LanOutlined' @@ -31,6 +32,14 @@ const getRuntimeTransactionLabel = (t: TFunction, method: string | undefined) => return t('transactions.method.consensus.delegate') case 'consensus.Undelegate': return t('transactions.method.consensus.undelegate') + case 'rofl.Create': + return t('transactions.method.rofl.create') + case 'rofl.Register': + return t('transactions.method.rofl.register') + case 'rofl.Remove': + return t('transactions.method.rofl.remove') + case 'rofl.Update': + return t('transactions.method.rofl.update') default: return method || t('common.unknown') } @@ -50,6 +59,10 @@ const getRuntimeTransactionLabel = (t: TFunction, method: string | undefined) => * - "consensus.Undelegate" * - "evm.Create" * - "evm.Call" + * - "rofl.Create" + * - "rofl.Update" + * - "rofl.Remove" + * - "rofl.Register" */ const getRuntimeTransactionIcon = (method: string | undefined, label: string, truncate?: boolean) => { const props = { @@ -73,6 +86,14 @@ const getRuntimeTransactionIcon = (method: string | undefined, label: string, tr return } {...props} /> case 'accounts.Transfer': return } {...props} /> + case 'rofl.Create': + return } {...props} /> + case 'rofl.Register': + return } {...props} /> + case 'rofl.Remove': + return } {...props} /> + case 'rofl.Update': + return } {...props} /> default: return } {...props} /> } diff --git a/src/app/pages/RuntimeTransactionDetailPage/index.tsx b/src/app/pages/RuntimeTransactionDetailPage/index.tsx index 0cd4c82ae..2df14eb7c 100644 --- a/src/app/pages/RuntimeTransactionDetailPage/index.tsx +++ b/src/app/pages/RuntimeTransactionDetailPage/index.tsx @@ -30,6 +30,8 @@ import { getFiatCurrencyForScope, showFiatValues } from '../../../config' import { convertToNano, getGasPrice } from '../../utils/number-utils' import { useWantedTransaction } from '../../hooks/useWantedTransaction' import { MultipleTransactionsWarning } from '../../components/Transactions/MultipleTransactionsWarning' +import { JsonCodeDisplay } from '../..//components/CodeDisplay' +import { isRoflTransaction } from '../../utils/transaction' export const RuntimeTransactionDetailPage: FC = () => { const { t } = useTranslation() @@ -242,6 +244,15 @@ export const RuntimeTransactionDetailView: FC<{ )} + {isRoflTransaction(transaction.method) && !!transaction.body && ( + <> +
{t('transaction.rawData')}
+
+ +
+ + )} + {!transaction.encryption_envelope && transaction.body?.init_code && ( <>
{t('transaction.rawData')}
diff --git a/src/app/utils/transaction.ts b/src/app/utils/transaction.ts index 9d66f547e..5b4d8f04c 100644 --- a/src/app/utils/transaction.ts +++ b/src/app/utils/transaction.ts @@ -28,3 +28,7 @@ export const getConsensusTransactionAmount = (transaction: Transaction) => { return undefined } } +export const isRoflTransaction = (method: string | undefined): boolean => { + const roflMethods = ['rofl.Create', 'rofl.Update', 'rofl.Remove', 'rofl.Register'] + return method ? roflMethods.includes(method) : false +} diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 0c25d934e..afb8cdf5c 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -449,6 +449,12 @@ "evm": { "call": "Contract Call", "create": "Contract Creation" + }, + "rofl": { + "create": "ROFL Create", + "register": "ROFL Register", + "remove": "ROFL Remove", + "update": "ROFL Update" } } }, @@ -478,6 +484,9 @@ "consensusDelegate": "Delegate to consensus", "consensusUndelegateStart": "Start to undelegate from consensus", "consensusUndelegateDone": "Undelegate from consensus finished", + "roflAppCreated": "ROFL App Created", + "roflAppUpdated": "ROFL App Updated", + "roflAppRemoved": "ROFL App Removed", "evmLog": "EVM log message", "filter": { "all": "All events", diff --git a/src/oasis-nexus/generated/api.ts b/src/oasis-nexus/generated/api.ts index 0edac56e4..ded7318b6 100644 --- a/src/oasis-nexus/generated/api.ts +++ b/src/oasis-nexus/generated/api.ts @@ -995,6 +995,10 @@ In practice, Nexus currently expects only the following methods: - "consensus.Undelegate" - "evm.Create" - "evm.Call" + - "rofl.Create" + - "rofl.Update" + - "rofl.Remove" + - "rofl.Register" May be null if the transaction was malformed or encrypted. */ method?: string; @@ -1162,6 +1166,9 @@ export const RuntimeEventType = { consensus_accountsundelegate_done: 'consensus_accounts.undelegate_done', coregas_used: 'core.gas_used', evmlog: 'evm.log', + roflapp_created: 'rofl.app_created', + roflapp_updated: 'rofl.app_updated', + roflapp_removed: 'rofl.app_removed', } as const; /** diff --git a/src/stories/Icons.stories.tsx b/src/stories/Icons.stories.tsx index 70d39d564..3540e8a32 100644 --- a/src/stories/Icons.stories.tsx +++ b/src/stories/Icons.stories.tsx @@ -14,7 +14,7 @@ export default { const Template: StoryFn = () => { return ( - + {Object.values(ConsensusTxMethod).map(method => ( { return ( - + {storyRuntimeMethods.map(method => ( { return ( - + {storyTokensMethods.map(method => ( { return ( - + {Object.values(RuntimeEventType).map(method => (