From 4663c795c3ed6479b45639511f57b4e0570ebe8e Mon Sep 17 00:00:00 2001 From: Max Korsunov Date: Fri, 14 Feb 2025 12:13:32 +0400 Subject: [PATCH] feat(ui): #2053: Add base for the ActionView component --- packages/ui/src/ActionView/action-view.tsx | 51 +++++++++++++++++++ .../src/ActionView/actions/incognito-icon.tsx | 18 +++++++ packages/ui/src/ActionView/actions/output.tsx | 15 ++++++ packages/ui/src/ActionView/actions/spend.tsx | 15 ++++++ .../ui/src/ActionView/actions/wrapper.tsx | 31 +++++++++++ packages/ui/src/ActionView/index.stories.tsx | 29 +++++++++++ packages/ui/src/ActionView/index.tsx | 3 ++ packages/ui/src/ActionView/types.ts | 5 ++ packages/ui/src/ActionView/unknown.tsx | 9 ++++ packages/ui/src/utils/bufs/action-view.ts | 51 +++++++++++++++++++ packages/ui/src/utils/bufs/index.ts | 1 + 11 files changed, 228 insertions(+) create mode 100644 packages/ui/src/ActionView/action-view.tsx create mode 100644 packages/ui/src/ActionView/actions/incognito-icon.tsx create mode 100644 packages/ui/src/ActionView/actions/output.tsx create mode 100644 packages/ui/src/ActionView/actions/spend.tsx create mode 100644 packages/ui/src/ActionView/actions/wrapper.tsx create mode 100644 packages/ui/src/ActionView/index.stories.tsx create mode 100644 packages/ui/src/ActionView/index.tsx create mode 100644 packages/ui/src/ActionView/types.ts create mode 100644 packages/ui/src/ActionView/unknown.tsx create mode 100644 packages/ui/src/utils/bufs/action-view.ts diff --git a/packages/ui/src/ActionView/action-view.tsx b/packages/ui/src/ActionView/action-view.tsx new file mode 100644 index 0000000000..3446794621 --- /dev/null +++ b/packages/ui/src/ActionView/action-view.tsx @@ -0,0 +1,51 @@ +import { ActionView as ActionViewMessage } from '@penumbra-zone/protobuf/penumbra/core/transaction/v1/transaction_pb'; +import { ActionViewType, ActionViewValueType } from './types'; +import { UnknownAction } from './unknown'; + +import { SpendAction } from './actions/spend'; +import { OutputAction } from './actions/output'; +import { FC } from 'react'; + +export interface ActionViewProps { + action: ActionViewMessage; +} + +const componentMap = { + spend: SpendAction, + output: OutputAction, + delegate: UnknownAction, + delegatorVote: UnknownAction, + ibcRelayAction: UnknownAction, + ics20Withdrawal: UnknownAction, + positionClose: UnknownAction, + positionOpen: UnknownAction, + positionRewardClaim: UnknownAction, + positionWithdraw: UnknownAction, + proposalDepositClaim: UnknownAction, + proposalSubmit: UnknownAction, + proposalWithdraw: UnknownAction, + swap: UnknownAction, + swapClaim: UnknownAction, + undelegate: UnknownAction, + undelegateClaim: UnknownAction, + validatorDefinition: UnknownAction, + validatorVote: UnknownAction, + actionDutchAuctionEnd: UnknownAction, + actionDutchAuctionSchedule: UnknownAction, + actionDutchAuctionWithdraw: UnknownAction, + communityPoolDeposit: UnknownAction, + communityPoolOutput: UnknownAction, + communityPoolSpend: UnknownAction, + unknown: UnknownAction, +} as const satisfies Record; + +/** + * In Penumbra, each transaction has 'actions' of different types, + * representing a blockchain state change performed by a transaction. + */ +export const ActionView = ({ action }: ActionViewProps) => { + const type = action.actionView.case ?? 'unknown'; + const Component = componentMap[type] as FC<{ value?: ActionViewValueType }>; + + return ; +}; diff --git a/packages/ui/src/ActionView/actions/incognito-icon.tsx b/packages/ui/src/ActionView/actions/incognito-icon.tsx new file mode 100644 index 0000000000..2f22c8a15b --- /dev/null +++ b/packages/ui/src/ActionView/actions/incognito-icon.tsx @@ -0,0 +1,18 @@ +export const IncognitoIcon = () => { + return ( + + + + ); +}; diff --git a/packages/ui/src/ActionView/actions/output.tsx b/packages/ui/src/ActionView/actions/output.tsx new file mode 100644 index 0000000000..2813b3c780 --- /dev/null +++ b/packages/ui/src/ActionView/actions/output.tsx @@ -0,0 +1,15 @@ +import { OutputView } from '@penumbra-zone/protobuf/penumbra/core/component/shielded_pool/v1/shielded_pool_pb'; +import { Density } from '../../Density'; +import { ActionWrapper } from './wrapper'; + +export interface SpendActionProps { + value: OutputView; +} + +export const OutputAction = ({ value }: SpendActionProps) => { + return ( + + {value.outputView.case === 'visible' && Outputsss} + + ); +}; diff --git a/packages/ui/src/ActionView/actions/spend.tsx b/packages/ui/src/ActionView/actions/spend.tsx new file mode 100644 index 0000000000..5f846be5aa --- /dev/null +++ b/packages/ui/src/ActionView/actions/spend.tsx @@ -0,0 +1,15 @@ +import { SpendView } from '@penumbra-zone/protobuf/penumbra/core/component/shielded_pool/v1/shielded_pool_pb'; +import { Density } from '../../Density'; +import { ActionWrapper } from './wrapper'; + +export interface SpendActionProps { + value: SpendView; +} + +export const SpendAction = ({ value }: SpendActionProps) => { + return ( + + {value.spendView.case === 'visible' && Actions} + + ); +}; diff --git a/packages/ui/src/ActionView/actions/wrapper.tsx b/packages/ui/src/ActionView/actions/wrapper.tsx new file mode 100644 index 0000000000..17a35ec787 --- /dev/null +++ b/packages/ui/src/ActionView/actions/wrapper.tsx @@ -0,0 +1,31 @@ +import { ReactNode } from 'react'; +import { IncognitoIcon } from './incognito-icon'; +import { Text } from '../../Text'; + +export interface ActionWrapperProps { + title: string; + opaque?: boolean; + children?: ReactNode; +} + +export const ActionWrapper = ({ opaque, children, title }: ActionWrapperProps) => { + // const density = useDensity(); + + return ( +
+ {opaque && ( + + + + )} + +
+ + {title} + +
+ + {!opaque &&
{children}
} +
+ ); +}; diff --git a/packages/ui/src/ActionView/index.stories.tsx b/packages/ui/src/ActionView/index.stories.tsx new file mode 100644 index 0000000000..21988d6ae3 --- /dev/null +++ b/packages/ui/src/ActionView/index.stories.tsx @@ -0,0 +1,29 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { ActionView as ActionViewMessage } from '@penumbra-zone/protobuf/penumbra/core/transaction/v1/transaction_pb'; + +import { ActionView } from '.'; +import { SpendAction } from '../utils/bufs'; + +const OPTIONS: Record = { + Spend: SpendAction, +}; + +const meta: Meta = { + component: ActionView, + tags: ['autodocs', '!dev', 'density'], + argTypes: { + action: { + options: Object.keys(OPTIONS), + mapping: OPTIONS, + }, + }, +}; +export default meta; + +type Story = StoryObj; + +export const Basic: Story = { + args: { + action: SpendAction, + }, +}; diff --git a/packages/ui/src/ActionView/index.tsx b/packages/ui/src/ActionView/index.tsx new file mode 100644 index 0000000000..c42976e8e0 --- /dev/null +++ b/packages/ui/src/ActionView/index.tsx @@ -0,0 +1,3 @@ +export { ActionView } from './action-view'; +export type { ActionViewProps } from './action-view'; +export type { ActionViewType } from './types'; diff --git a/packages/ui/src/ActionView/types.ts b/packages/ui/src/ActionView/types.ts new file mode 100644 index 0000000000..066bdabd2a --- /dev/null +++ b/packages/ui/src/ActionView/types.ts @@ -0,0 +1,5 @@ +import { ActionView } from '@penumbra-zone/protobuf/penumbra/core/transaction/v1/transaction_pb'; + +export type ActionViewType = Exclude; + +export type ActionViewValueType = Exclude; diff --git a/packages/ui/src/ActionView/unknown.tsx b/packages/ui/src/ActionView/unknown.tsx new file mode 100644 index 0000000000..957008a775 --- /dev/null +++ b/packages/ui/src/ActionView/unknown.tsx @@ -0,0 +1,9 @@ +import { Text } from '../Text'; + +export const UnknownAction = () => { + return ( +
+ Unknown action +
+ ); +}; diff --git a/packages/ui/src/utils/bufs/action-view.ts b/packages/ui/src/utils/bufs/action-view.ts new file mode 100644 index 0000000000..b31321b642 --- /dev/null +++ b/packages/ui/src/utils/bufs/action-view.ts @@ -0,0 +1,51 @@ +import { ActionView } from '@penumbra-zone/protobuf/penumbra/core/transaction/v1/transaction_pb'; +import { SpendView } from '@penumbra-zone/protobuf/penumbra/core/component/shielded_pool/v1/shielded_pool_pb'; + +export const SpendAction = new ActionView({ + actionView: { + case: 'spend', + value: new SpendView({ + spendView: { + case: 'visible', + value: { + note: { + address: { + addressView: { + case: 'decoded', + value: { + address: { + inner: Uint8Array.from([0, 1, 2, 3]), + }, + index: { + account: 0, + }, + }, + }, + }, + value: { + valueView: { + case: 'unknownAssetId', + value: { + amount: { + hi: 1n, + lo: 0n, + }, + assetId: { + inner: Uint8Array.from([0, 1, 2, 3]), + }, + }, + }, + }, + }, + spend: { + body: { + balanceCommitment: { + inner: Uint8Array.from([0, 1, 2, 3]), + }, + }, + }, + }, + }, + }), + }, +}); diff --git a/packages/ui/src/utils/bufs/index.ts b/packages/ui/src/utils/bufs/index.ts index 19f47a03ee..c57c01e9b7 100644 --- a/packages/ui/src/utils/bufs/index.ts +++ b/packages/ui/src/utils/bufs/index.ts @@ -7,3 +7,4 @@ export * from './metadata'; export * from './value-view'; export * from './address-view'; export * from './balances-responses'; +export * from './action-view';