From fa2cd31fe3c9cb075d0bd565247ea9589dff6afc Mon Sep 17 00:00:00 2001 From: Steven Date: Tue, 10 Dec 2024 07:22:05 +0100 Subject: [PATCH] feat(rwa): add asset (#2706) --- .changeset/curvy-mice-destroy.md | 2 + .changeset/popular-rice-search.md | 2 + .../rwa-demo/src/app/(app)/assets/page.tsx | 112 +- .../apps/rwa-demo/src/app/(app)/layout.tsx | 13 +- .../src/components/AgentForm/AgentForm.tsx | 5 + .../src/components/AgentsList/AgentsList.tsx | 11 +- .../AssetForm/AddExistingAssetForm.tsx | 52 + .../src/components/AssetForm/AssetForm.tsx | 51 + .../components/AssetForm/StepperAssetForm.tsx | 202 +++ .../src/components/AssetInfo/AssetInfo.tsx | 2 +- .../AssetProvider/AssetProvider.tsx | 79 +- .../src/components/AssetSwitch/AssetForm.tsx | 98 -- .../components/AssetSwitch/AssetSwitch.tsx | 36 +- .../TableFormatters/FormatAgentRoles.tsx | 34 + .../TransactionsProvider.tsx | 1 + .../apps/rwa-demo/src/hooks/createContract.ts | 46 + .../src/hooks/createPrincipalNamespace.ts | 41 + packages/apps/rwa-demo/src/hooks/freeze.ts | 2 +- .../apps/rwa-demo/src/hooks/getAgentRoles.ts | 24 + packages/apps/rwa-demo/src/hooks/getAgents.ts | 8 +- .../apps/rwa-demo/src/hooks/getInvestors.ts | 4 +- .../apps/rwa-demo/src/hooks/initContract.ts | 50 + packages/apps/rwa-demo/src/hooks/paused.ts | 4 +- packages/apps/rwa-demo/src/hooks/supply.ts | 2 +- .../apps/rwa-demo/src/services/addAgent.ts | 6 +- .../rwa-demo/src/services/createContract.ts | 28 + .../src/services/createPrincipalNamespace.ts | 37 + .../rwa-demo/src/services/deleteIdentity.ts | 4 +- .../rwa-demo/src/services/distributeTokens.ts | 15 +- .../rwa-demo/src/services/getAgentRoles.ts | 34 + .../src/services/getAssetMaxSupplyBalance.ts | 72 +- .../apps/rwa-demo/src/services/getBalance.ts | 2 +- .../rwa-demo/src/services/getFrozenTokens.ts | 4 +- .../rwa-demo/src/services/initContract.ts | 36 + .../apps/rwa-demo/src/services/isAgent.ts | 2 +- .../src/services/isComplianceOwner.ts | 10 +- .../apps/rwa-demo/src/services/isFrozen.ts | 2 +- .../apps/rwa-demo/src/services/isInvestor.ts | 2 +- .../apps/rwa-demo/src/services/isOwner.ts | 7 +- .../apps/rwa-demo/src/services/isPaused.ts | 2 +- .../src/services/pact/modalcontract.ts | 1154 +++++++++++++++++ packages/apps/rwa-demo/src/services/paused.ts | 2 +- .../rwa-demo/src/services/registerIdentity.ts | 6 +- .../apps/rwa-demo/src/services/removeAgent.ts | 4 +- .../rwa-demo/src/services/setAddressFrozen.ts | 4 +- .../rwa-demo/src/services/setCompliance.ts | 4 +- packages/apps/rwa-demo/src/services/supply.ts | 2 +- .../services/togglePartiallyFreezeTokens.ts | 4 +- .../apps/rwa-demo/src/services/togglePause.ts | 4 +- .../rwa-demo/src/services/transferTokens.ts | 4 +- packages/apps/rwa-demo/src/utils/getAsset.ts | 6 +- .../apps/rwa-demo/src/utils/store/index.ts | 15 +- .../LayoutProvider/NotificationsProvider.tsx | 6 +- 53 files changed, 2109 insertions(+), 250 deletions(-) create mode 100644 .changeset/curvy-mice-destroy.md create mode 100644 .changeset/popular-rice-search.md create mode 100644 packages/apps/rwa-demo/src/components/AssetForm/AddExistingAssetForm.tsx create mode 100644 packages/apps/rwa-demo/src/components/AssetForm/AssetForm.tsx create mode 100644 packages/apps/rwa-demo/src/components/AssetForm/StepperAssetForm.tsx delete mode 100644 packages/apps/rwa-demo/src/components/AssetSwitch/AssetForm.tsx create mode 100644 packages/apps/rwa-demo/src/components/TableFormatters/FormatAgentRoles.tsx create mode 100644 packages/apps/rwa-demo/src/hooks/createContract.ts create mode 100644 packages/apps/rwa-demo/src/hooks/createPrincipalNamespace.ts create mode 100644 packages/apps/rwa-demo/src/hooks/getAgentRoles.ts create mode 100644 packages/apps/rwa-demo/src/hooks/initContract.ts create mode 100644 packages/apps/rwa-demo/src/services/createContract.ts create mode 100644 packages/apps/rwa-demo/src/services/createPrincipalNamespace.ts create mode 100644 packages/apps/rwa-demo/src/services/getAgentRoles.ts create mode 100644 packages/apps/rwa-demo/src/services/initContract.ts create mode 100644 packages/apps/rwa-demo/src/services/pact/modalcontract.ts diff --git a/.changeset/curvy-mice-destroy.md b/.changeset/curvy-mice-destroy.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/curvy-mice-destroy.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.changeset/popular-rice-search.md b/.changeset/popular-rice-search.md new file mode 100644 index 0000000000..a845151cc8 --- /dev/null +++ b/.changeset/popular-rice-search.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/packages/apps/rwa-demo/src/app/(app)/assets/page.tsx b/packages/apps/rwa-demo/src/app/(app)/assets/page.tsx index d5f383a94e..d6e5fd9379 100644 --- a/packages/apps/rwa-demo/src/app/(app)/assets/page.tsx +++ b/packages/apps/rwa-demo/src/app/(app)/assets/page.tsx @@ -1,34 +1,102 @@ 'use client'; +import { AssetForm } from '@/components/AssetForm/AssetForm'; +import { Confirmation } from '@/components/Confirmation/Confirmation'; import { useAsset } from '@/hooks/asset'; -import { CompactTable, CompactTableFormatters } from '@kadena/kode-ui/patterns'; +import { MonoAdd, MonoDelete } from '@kadena/kode-icons'; +import { Button } from '@kadena/kode-ui'; +import { + CompactTable, + CompactTableFormatters, + RightAside, + RightAsideContent, + RightAsideHeader, + SectionCard, + SectionCardBody, + SectionCardContentBlock, + SectionCardHeader, + useLayout, +} from '@kadena/kode-ui/patterns'; import Link from 'next/link'; +import { useState } from 'react'; const Assets = () => { - const { assets } = useAsset(); + const { assets, removeAsset } = useAsset(); + const [openSide, setOpenSide] = useState(false); + const { setIsRightAsideExpanded, isRightAsideExpanded } = useLayout(); + + const handleDelete = (value: any) => { + removeAsset(value); + }; return ( <> - + {isRightAsideExpanded && openSide && ( + { + setIsRightAsideExpanded(false); + setOpenSide(false); + }} + > + + + + )} + + + List of all your selected contracts} + actions={ + }> + Add Asset + + } + /> + } + /> + + } + /> + } + > + Are you sure you want to remove this asset? + + ), + }), + }, + ]} + data={assets} + /> + + + ); }; diff --git a/packages/apps/rwa-demo/src/app/(app)/layout.tsx b/packages/apps/rwa-demo/src/app/(app)/layout.tsx index 4b44513c56..6910989fb4 100644 --- a/packages/apps/rwa-demo/src/app/(app)/layout.tsx +++ b/packages/apps/rwa-demo/src/app/(app)/layout.tsx @@ -9,13 +9,15 @@ import { } from '@kadena/kode-ui/patterns'; import { ActiveTransactionsList } from '@/components/ActiveTransactionsList/ActiveTransactionsList'; +import { StepperAssetForm } from '@/components/AssetForm/StepperAssetForm'; import { AssetInfo } from '@/components/AssetInfo/AssetInfo'; -import { AssetForm } from '@/components/AssetSwitch/AssetForm'; import { TransactionPendingIcon } from '@/components/TransactionPendingIcon/TransactionPendingIcon'; +import { useAccount } from '@/hooks/account'; import { useTransactions } from '@/hooks/transactions'; import { getAsset } from '@/utils/getAsset'; import { MonoAccountBalanceWallet } from '@kadena/kode-icons'; import { Button, Heading, Link, Stack } from '@kadena/kode-ui'; +import { useRouter } from 'next/navigation'; import React, { useEffect, useRef, useState } from 'react'; import { KLogo } from './KLogo'; import { SideBar } from './SideBar'; @@ -25,12 +27,14 @@ const RootLayout = ({ }: Readonly<{ children: React.ReactNode; }>) => { + const { account, isMounted } = useAccount(); const [openTransactionsSide, setOpenTransactionsSide] = useState(false); const { setIsRightAsideExpanded, isRightAsideExpanded } = useLayout(); const { transactions, setTxsButtonRef, setTxsAnimationRef } = useTransactions(); const txsButtonRef = useRef(null); const transactionAnimationRef = useRef(null); + const router = useRouter(); useEffect(() => { if (!txsButtonRef.current || !transactionAnimationRef.current) return; @@ -38,6 +42,11 @@ const RootLayout = ({ setTxsAnimationRef(transactionAnimationRef.current); }, [txsButtonRef.current, transactionAnimationRef.current]); + if (isMounted && !account) { + router.replace('/login'); + return; + } + if (!getAsset()) { return (
Add new asset - +
); diff --git a/packages/apps/rwa-demo/src/components/AgentForm/AgentForm.tsx b/packages/apps/rwa-demo/src/components/AgentForm/AgentForm.tsx index 2b3b6c6928..4413c8ff5d 100644 --- a/packages/apps/rwa-demo/src/components/AgentForm/AgentForm.tsx +++ b/packages/apps/rwa-demo/src/components/AgentForm/AgentForm.tsx @@ -21,9 +21,13 @@ interface IProps { } export const AgentForm: FC = ({ onClose, agent, trigger }) => { + // const { data: userAgentRolesData } = useGetAgentRoles({ + // agent: agent?.accountName, + // }); const { submit } = useEditAgent(); const [isOpen, setIsOpen] = useState(false); const { setIsRightAsideExpanded, isRightAsideExpanded } = useLayout(); + const { handleSubmit, control, @@ -60,6 +64,7 @@ export const AgentForm: FC = ({ onClose, agent, trigger }) => { }; const onSubmit = async (data: IAddAgentProps) => { + console.log({ data }); await submit(data); handleOnClose(); }; diff --git a/packages/apps/rwa-demo/src/components/AgentsList/AgentsList.tsx b/packages/apps/rwa-demo/src/components/AgentsList/AgentsList.tsx index 81f6c7a975..ddf64812c5 100644 --- a/packages/apps/rwa-demo/src/components/AgentsList/AgentsList.tsx +++ b/packages/apps/rwa-demo/src/components/AgentsList/AgentsList.tsx @@ -19,6 +19,7 @@ import { useRouter } from 'next/navigation'; import type { FC } from 'react'; import { AgentForm } from '../AgentForm/AgentForm'; import { Confirmation } from '../Confirmation/Confirmation'; +import { FormatAgentRoles } from '../TableFormatters/FormatAgentRoles'; export const AgentsList: FC = () => { const { paused } = useAsset(); @@ -63,14 +64,20 @@ export const AgentsList: FC = () => { { label: 'Name', key: 'alias', - width: '30%', + width: '20%', }, { label: 'Account', key: 'accountName', - width: '50%', + width: '20%', render: CompactTableFormatters.FormatAccount(), }, + { + label: 'Roles', + key: 'accountName', + width: '40%', + render: FormatAgentRoles(), + }, { label: '', key: 'accountName', diff --git a/packages/apps/rwa-demo/src/components/AssetForm/AddExistingAssetForm.tsx b/packages/apps/rwa-demo/src/components/AssetForm/AddExistingAssetForm.tsx new file mode 100644 index 0000000000..914a9cf4af --- /dev/null +++ b/packages/apps/rwa-demo/src/components/AssetForm/AddExistingAssetForm.tsx @@ -0,0 +1,52 @@ +import { useAsset } from '@/hooks/asset'; +import { Button, Stack, TextField } from '@kadena/kode-ui'; +import { useRouter } from 'next/navigation'; +import type { FC } from 'react'; +import { Controller, useForm } from 'react-hook-form'; + +interface IAddExistingAssetProps { + name: string; +} + +export const AddExistingAssetForm: FC = () => { + const router = useRouter(); + const { addExistingAsset } = useAsset(); + const { + handleSubmit, + control, + formState: { isValid }, + } = useForm({ + values: { + name: '', + }, + }); + + const handleSave = async (data: IAddExistingAssetProps) => { + const asset = addExistingAsset(data.name); + if (!asset) return; + + router.refresh(); + }; + + return ( + + ( + + )} + /> + + + + ); +}; diff --git a/packages/apps/rwa-demo/src/components/AssetForm/AssetForm.tsx b/packages/apps/rwa-demo/src/components/AssetForm/AssetForm.tsx new file mode 100644 index 0000000000..2b7079b60b --- /dev/null +++ b/packages/apps/rwa-demo/src/components/AssetForm/AssetForm.tsx @@ -0,0 +1,51 @@ +import { + RightAside, + RightAsideContent, + RightAsideHeader, + useLayout, +} from '@kadena/kode-ui/patterns'; +import type { FC, ReactElement } from 'react'; +import { cloneElement, useState } from 'react'; +import type { IAsset } from '../AssetProvider/AssetProvider'; +import { StepperAssetForm } from './StepperAssetForm'; + +interface IProps { + asset?: IAsset; + trigger: ReactElement; + onClose?: () => void; +} + +export const AssetForm: FC = ({ trigger, onClose }) => { + const [isOpen, setIsOpen] = useState(false); + const { setIsRightAsideExpanded, isRightAsideExpanded } = useLayout(); + + const handleOpen = () => { + setIsRightAsideExpanded(true); + setIsOpen(true); + if (trigger.props.onPress) trigger.props.onPress(); + }; + + const handleOnClose = () => { + setIsRightAsideExpanded(false); + setIsOpen(false); + if (onClose) onClose(); + }; + + return ( + <> + {isRightAsideExpanded && isOpen && ( + + + + + + + )} + + {cloneElement(trigger, { ...trigger.props, onPress: handleOpen })} + + ); +}; diff --git a/packages/apps/rwa-demo/src/components/AssetForm/StepperAssetForm.tsx b/packages/apps/rwa-demo/src/components/AssetForm/StepperAssetForm.tsx new file mode 100644 index 0000000000..15182a7127 --- /dev/null +++ b/packages/apps/rwa-demo/src/components/AssetForm/StepperAssetForm.tsx @@ -0,0 +1,202 @@ +import { useAsset } from '@/hooks/asset'; +import { useCreateContract } from '@/hooks/createContract'; +import { useCreatePrincipalNamespace } from '@/hooks/createPrincipalNamespace'; +import { useInitContract } from '@/hooks/initContract'; +import type { IAddContractProps } from '@/services/createContract'; +import { + Button, + Notification, + NotificationHeading, + Stack, + Step, + Stepper, + TextField, +} from '@kadena/kode-ui'; +import { useRouter } from 'next/navigation'; +import type { FC } from 'react'; +import { useState } from 'react'; +import { Controller, useForm } from 'react-hook-form'; +import type { IAsset } from '../AssetProvider/AssetProvider'; +import { AddExistingAssetForm } from './AddExistingAssetForm'; + +interface IProps { + asset?: IAsset; +} + +const STEPS = { + CREATE_NAMESPACE: 0, + CREATE_CONTRACT: 1, + INIT_CONTRACT: 2, + DONE: 3, +} as const; + +export const StepperAssetForm: FC = () => { + const [contractData, setContractData] = useState< + IAddContractProps | undefined + >(); + const [step, setStep] = useState(STEPS.CREATE_NAMESPACE); + const { addAsset, setAsset } = useAsset(); + const { submit } = useCreatePrincipalNamespace(); + const { submit: submitInit } = useInitContract(); + const { submit: submitContract } = useCreateContract(); + const [namespace, setNamespace] = useState(''); + const [error, setError] = useState(''); + const router = useRouter(); + + const { + handleSubmit, + control, + formState: { isValid }, + } = useForm({ + values: { + contractName: 'asd', + owner: + 'k:9f6a3e6ed941c9abe2c9d12afea3fe55644282c2392fe7e9571e3822d21db229', + complianceOwner: + 'k:9f6a3e6ed941c9abe2c9d12afea3fe55644282c2392fe7e9571e3822d21db229', + namespace, + }, + }); + + const handleSave = async (data: IAddContractProps) => { + setContractData(data); + const tx = await submitContract(data); + if (tx?.result?.status === 'success') { + setStep(STEPS.INIT_CONTRACT); + } + }; + + return ( + + + = STEPS.CREATE_NAMESPACE ? 'active' : 'inactive'} + active={step === STEPS.CREATE_NAMESPACE} + > + Namespace + + = STEPS.CREATE_CONTRACT ? 'active' : 'inactive'} + active={step === STEPS.CREATE_CONTRACT} + > + Contract + + = STEPS.INIT_CONTRACT ? 'active' : 'inactive'} + active={step === STEPS.INIT_CONTRACT} + > + Init + + + + {error && ( + + There was an issue + {error} + + )} + + {step === STEPS.CREATE_NAMESPACE && ( + + + + + )} + {step === STEPS.INIT_CONTRACT && ( + + )} + + {step === STEPS.DONE && ( + + )} + + {step === STEPS.CREATE_CONTRACT && ( +
+ } + /> + + ( + + )} + /> + + } + /> + + ( + + )} + /> + + + + + )} +
+ ); +}; diff --git a/packages/apps/rwa-demo/src/components/AssetInfo/AssetInfo.tsx b/packages/apps/rwa-demo/src/components/AssetInfo/AssetInfo.tsx index 07e7a3f952..bad6f4f011 100644 --- a/packages/apps/rwa-demo/src/components/AssetInfo/AssetInfo.tsx +++ b/packages/apps/rwa-demo/src/components/AssetInfo/AssetInfo.tsx @@ -9,7 +9,7 @@ export const AssetInfo: FC = () => { if (!asset) return; return ( - {asset.name} + {asset.contractName}