diff --git a/packages/apps/rwa-demo/src/app/(app)/layout.tsx b/packages/apps/rwa-demo/src/app/(app)/layout.tsx
index 3ab1e7a11a..9953c1c48b 100644
--- a/packages/apps/rwa-demo/src/app/(app)/layout.tsx
+++ b/packages/apps/rwa-demo/src/app/(app)/layout.tsx
@@ -11,6 +11,7 @@ import {
import { ActiveTransactionsList } from '@/components/ActiveTransactionsList/ActiveTransactionsList';
import { AssetInfo } from '@/components/AssetInfo/AssetInfo';
import { DemoBanner } from '@/components/DemoBanner/DemoBanner';
+import { FrozenInvestorBanner } from '@/components/FrozenInvestorBanner/FrozenInvestorBanner';
import { GraphOnlineBanner } from '@/components/GraphOnlineBanner/GraphOnlineBanner';
import { TransactionPendingIcon } from '@/components/TransactionPendingIcon/TransactionPendingIcon';
import { useAccount } from '@/hooks/account';
@@ -92,6 +93,7 @@ const RootLayout = ({
+
}
logo={
diff --git a/packages/apps/rwa-demo/src/components/BadgeFeezeForm/BadgeFeezeForm.tsx b/packages/apps/rwa-demo/src/components/BadgeFeezeForm/BadgeFeezeForm.tsx
deleted file mode 100644
index 36b541589a..0000000000
--- a/packages/apps/rwa-demo/src/components/BadgeFeezeForm/BadgeFeezeForm.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import { useBatchFreezeInvestors } from '@/hooks/batchFreezeInvestors';
-import type { IBatchSetAddressFrozenProps } from '@/services/batchSetAddressFrozen';
-import { MonoPause, MonoPlayArrow } from '@kadena/kode-icons';
-import { Button } from '@kadena/kode-ui';
-
-import { useAccount } from '@/hooks/account';
-import type { FC } from 'react';
-import type { UseFormHandleSubmit, UseFormReset } from 'react-hook-form';
-import { TransactionTypeSpinner } from '../TransactionTypeSpinner/TransactionTypeSpinner';
-import { TXTYPES } from '../TransactionsProvider/TransactionsProvider';
-
-interface IProps {
- pause: boolean;
- isDisabled: boolean;
- handleReset: UseFormReset<{
- select: [];
- }>;
- handleSubmit: UseFormHandleSubmit<
- {
- select: [];
- },
- undefined
- >;
-}
-
-export const BadgeFreezeForm: FC = ({
- handleSubmit,
- handleReset,
- isDisabled,
- pause,
-}) => {
- const { account } = useAccount();
- const { submit, isAllowed } = useBatchFreezeInvestors();
-
- const onSubmit = async ({ select }: { select: string[] }) => {
- const data: IBatchSetAddressFrozenProps = {
- investorAccounts: select,
- pause,
- };
- const tx = await submit(data);
- tx?.listener.subscribe(
- () => {},
- () => {},
- () => {
- handleReset({ select: [] });
- },
- );
- };
-
- return (
- : }
- />
- }
- >
- {pause ? 'Freeze' : 'Unfreeze'}
-
- );
-};
diff --git a/packages/apps/rwa-demo/src/components/BadgeFreezeForm/BadgeFreezeForm.tsx b/packages/apps/rwa-demo/src/components/BadgeFreezeForm/BadgeFreezeForm.tsx
new file mode 100644
index 0000000000..5bc47ef807
--- /dev/null
+++ b/packages/apps/rwa-demo/src/components/BadgeFreezeForm/BadgeFreezeForm.tsx
@@ -0,0 +1,117 @@
+import { useBatchFreezeInvestors } from '@/hooks/batchFreezeInvestors';
+import type { IBatchSetAddressFrozenProps } from '@/services/batchSetAddressFrozen';
+import { MonoPause, MonoPlayArrow } from '@kadena/kode-icons';
+import {
+ Button,
+ Dialog,
+ DialogContent,
+ DialogFooter,
+ DialogHeader,
+ TextareaField,
+} from '@kadena/kode-ui';
+
+import { useAccount } from '@/hooks/account';
+import type { ChangeEvent, FC } from 'react';
+import { useState } from 'react';
+import type { UseFormHandleSubmit, UseFormReset } from 'react-hook-form';
+import { TransactionTypeSpinner } from '../TransactionTypeSpinner/TransactionTypeSpinner';
+import { TXTYPES } from '../TransactionsProvider/TransactionsProvider';
+
+interface IProps {
+ pause: boolean;
+ isDisabled: boolean;
+ handleReset: UseFormReset<{
+ select: [];
+ }>;
+ handleSubmit: UseFormHandleSubmit<
+ {
+ select: [];
+ },
+ undefined
+ >;
+}
+
+export const BadgeFreezeForm: FC = ({
+ handleSubmit,
+ handleReset,
+ isDisabled,
+ pause,
+}) => {
+ const [isModalOpen, setIsModalOpen] = useState(false);
+ const [message, setMessage] = useState('');
+ const { account } = useAccount();
+ const { submit, isAllowed } = useBatchFreezeInvestors();
+
+ const onSubmit = async ({ select }: { select: string[] }) => {
+ const data: IBatchSetAddressFrozenProps = {
+ investorAccounts: select,
+ pause,
+ message,
+ };
+ const tx = await submit(data);
+ setIsModalOpen(false);
+ tx?.listener.subscribe(
+ () => {},
+ () => {},
+ () => {
+ handleReset({ select: [] });
+ },
+ );
+ };
+
+ const handleMessageChange = (e: ChangeEvent) => {
+ setMessage((e.target as HTMLTextAreaElement).value);
+ };
+
+ const handleStart = async () => {
+ if (pause) {
+ setIsModalOpen(true);
+ return;
+ }
+ };
+
+ return (
+ <>
+ {pause && (
+
+ )}
+ : }
+ />
+ }
+ >
+ {pause ? 'Freeze' : 'Unfreeze'}
+
+ >
+ );
+};
diff --git a/packages/apps/rwa-demo/src/components/DemoBanner/DemoBanner.tsx b/packages/apps/rwa-demo/src/components/DemoBanner/DemoBanner.tsx
index 762a0d820c..0ccafc786c 100644
--- a/packages/apps/rwa-demo/src/components/DemoBanner/DemoBanner.tsx
+++ b/packages/apps/rwa-demo/src/components/DemoBanner/DemoBanner.tsx
@@ -3,7 +3,7 @@ import type { FC } from 'react';
export const DemoBanner: FC = () => {
return (
-
+
This is a demo app. And is not running on Mainnet
diff --git a/packages/apps/rwa-demo/src/components/FreezeInvestor/FreezeInvestor.tsx b/packages/apps/rwa-demo/src/components/FreezeInvestor/FreezeInvestor.tsx
index d33741ec72..b1cc3892ec 100644
--- a/packages/apps/rwa-demo/src/components/FreezeInvestor/FreezeInvestor.tsx
+++ b/packages/apps/rwa-demo/src/components/FreezeInvestor/FreezeInvestor.tsx
@@ -2,9 +2,20 @@ import { useFreeze } from '@/hooks/freeze';
import { useFreezeInvestor } from '@/hooks/freezeInvestor';
import { MonoPause, MonoPlayArrow } from '@kadena/kode-icons';
import type { IButtonProps } from '@kadena/kode-ui';
-import { Button } from '@kadena/kode-ui';
+import {
+ Button,
+ Dialog,
+ DialogContent,
+ DialogFooter,
+ DialogHeader,
+ DialogHeaderSubtitle,
+ maskValue,
+ Text,
+ TextareaField,
+} from '@kadena/kode-ui';
import type { FC } from 'react';
import React, { useEffect, useState } from 'react';
+import { useForm } from 'react-hook-form';
import { SendTransactionAnimation } from '../SendTransactionAnimation/SendTransactionAnimation';
import { TransactionPendingIcon } from '../TransactionPendingIcon/TransactionPendingIcon';
import { TXTYPES } from '../TransactionsProvider/TransactionsProvider';
@@ -30,25 +41,48 @@ export const FreezeInvestor: FC = ({
isCompact,
variant,
}) => {
+ const [isModalOpen, setIsModalOpen] = useState(false);
const { frozen } = useFreeze({ investorAccount });
const [isLoading, setIsLoading] = useState(true);
const { submit, isAllowed } = useFreezeInvestor();
- const handleFreeze = async () => {
+ const {
+ register,
+ handleSubmit,
+ formState: { isValid },
+ } = useForm<{ message: string }>({
+ values: {
+ message: '',
+ },
+ });
+
+ const handleFreeze = async (data?: { message: string }) => {
if (frozen === undefined) return;
- const data = {
+ const newData = {
investorAccount: investorAccount,
pause: !frozen,
+ message: data?.message,
};
try {
setIsLoading(true);
- return await submit(data);
+ return await submit(newData);
} catch (e: any) {
setIsLoading(false);
+ } finally {
+ setIsModalOpen(false);
}
};
+ const handleStart = async () => {
+ if (frozen === undefined || frozen === false) {
+ setIsModalOpen(true);
+ return;
+ }
+
+ await handleFreeze();
+ };
+
useEffect(() => {
setIsLoading(false);
}, [frozen]);
@@ -56,24 +90,56 @@ export const FreezeInvestor: FC = ({
const label = iconOnly ? '' : frozen ? 'Unfreeze account' : 'Freeze account';
return (
-
+
+
+
+
+
+
+
+
+
+ }
+ isDisabled={!isAllowed}
+ isCompact={isCompact}
+ variant={variant}
+ >
+ {label}
+
+ }
+ >
+ >
);
};
diff --git a/packages/apps/rwa-demo/src/components/FrozenInvestorBanner/FrozenInvestorBanner.tsx b/packages/apps/rwa-demo/src/components/FrozenInvestorBanner/FrozenInvestorBanner.tsx
new file mode 100644
index 0000000000..353787cb63
--- /dev/null
+++ b/packages/apps/rwa-demo/src/components/FrozenInvestorBanner/FrozenInvestorBanner.tsx
@@ -0,0 +1,9 @@
+import { useAccount } from '@/hooks/account';
+import type { FC } from 'react';
+import { InvestorFrozenMessage } from '../InvestorFrozenMessage/InvestorFrozenMessage';
+
+export const FrozenInvestorBanner: FC = () => {
+ const { account } = useAccount();
+ if (!account) return;
+ return ;
+};
diff --git a/packages/apps/rwa-demo/src/components/InvestorFrozenMessage/InvestorFrozenMessage.tsx b/packages/apps/rwa-demo/src/components/InvestorFrozenMessage/InvestorFrozenMessage.tsx
index 0ae8b6eb17..2226267d06 100644
--- a/packages/apps/rwa-demo/src/components/InvestorFrozenMessage/InvestorFrozenMessage.tsx
+++ b/packages/apps/rwa-demo/src/components/InvestorFrozenMessage/InvestorFrozenMessage.tsx
@@ -1,18 +1,37 @@
+import { useAccount } from '@/hooks/account';
import { useFreeze } from '@/hooks/freeze';
-import { Notification } from '@kadena/kode-ui';
+import { store } from '@/utils/store';
+import { Notification, NotificationHeading } from '@kadena/kode-ui';
import type { FC } from 'react';
+import { useEffect, useState } from 'react';
interface IProps {
investorAccount: string;
}
export const InvestorFrozenMessage: FC = ({ investorAccount }) => {
+ const { isInvestor, account } = useAccount();
const { frozen } = useFreeze({ investorAccount });
+ const [message, setMessage] = useState();
- if (!frozen) return;
+ const init = async () => {
+ if (!account) return;
+ const result = await store.getFrozenMessage(account.address);
+ setMessage(result);
+ };
+
+ useEffect(() => {
+ if (!isInvestor || !account) return;
+
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
+ init();
+ }, [frozen, isInvestor, account]);
+
+ if (!frozen || !isInvestor || !account) return;
return (
-
- The investor account is frozen
+
+ The investor account is frozen
+ {message}
);
};
diff --git a/packages/apps/rwa-demo/src/components/InvestorList/InvestorList.tsx b/packages/apps/rwa-demo/src/components/InvestorList/InvestorList.tsx
index edf8a7e405..ce8cfb3f24 100644
--- a/packages/apps/rwa-demo/src/components/InvestorList/InvestorList.tsx
+++ b/packages/apps/rwa-demo/src/components/InvestorList/InvestorList.tsx
@@ -15,7 +15,7 @@ import { useRouter } from 'next/navigation';
import type { FC } from 'react';
import { useRef } from 'react';
import { useForm } from 'react-hook-form';
-import { BadgeFreezeForm } from '../BadgeFeezeForm/BadgeFeezeForm';
+import { BadgeFreezeForm } from '../BadgeFreezeForm/BadgeFreezeForm';
import { InvestorBatchForm } from '../InvestorBatchForm/InvestorBatchForm';
import { InvestorForm } from '../InvestorForm/InvestorForm';
import { FormatCheckbox } from '../TableFormatters/FormatCheckbox';
diff --git a/packages/apps/rwa-demo/src/hooks/batchFreezeInvestors.ts b/packages/apps/rwa-demo/src/hooks/batchFreezeInvestors.ts
index 65a3b027d8..ef5bd30f51 100644
--- a/packages/apps/rwa-demo/src/hooks/batchFreezeInvestors.ts
+++ b/packages/apps/rwa-demo/src/hooks/batchFreezeInvestors.ts
@@ -6,6 +6,7 @@ import {
import type { IBatchSetAddressFrozenProps } from '@/services/batchSetAddressFrozen';
import { batchSetAddressFrozen } from '@/services/batchSetAddressFrozen';
import { getClient } from '@/utils/client';
+import { store } from '@/utils/store';
import { useNotifications } from '@kadena/kode-ui/patterns';
import { useEffect, useState } from 'react';
import { useAccount } from './account';
@@ -24,7 +25,10 @@ export const useBatchFreezeInvestors = () => {
): Promise => {
try {
const tx = await batchSetAddressFrozen(data, account!);
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
+ await store.setFrozenMessages(data);
const signedTransaction = await sign(tx);
+
if (!signedTransaction) return;
const client = getClient();
diff --git a/packages/apps/rwa-demo/src/hooks/freeze.ts b/packages/apps/rwa-demo/src/hooks/freeze.ts
index e09d262fea..cb81f6f488 100644
--- a/packages/apps/rwa-demo/src/hooks/freeze.ts
+++ b/packages/apps/rwa-demo/src/hooks/freeze.ts
@@ -55,10 +55,13 @@ export const useFreeze = ({
useEffect(() => {
if (!data?.events?.length) return;
- const params = JSON.parse(data?.events[0].parameters ?? '[]');
- if (params.length < 2 || params[0] !== investorAccount) return;
- setFrozen(params[1]);
+ data?.events?.map((evt) => {
+ const params = JSON.parse(evt.parameters ?? '[]');
+ if (params.length < 2 || params[0] !== investorAccount) return;
+
+ setFrozen(params[1]);
+ });
}, [data]);
return { frozen };
diff --git a/packages/apps/rwa-demo/src/hooks/freezeInvestor.ts b/packages/apps/rwa-demo/src/hooks/freezeInvestor.ts
index 248873a2bb..55b21fea66 100644
--- a/packages/apps/rwa-demo/src/hooks/freezeInvestor.ts
+++ b/packages/apps/rwa-demo/src/hooks/freezeInvestor.ts
@@ -6,6 +6,7 @@ import {
import type { ISetAddressFrozenProps } from '@/services/setAddressFrozen';
import { setAddressFrozen } from '@/services/setAddressFrozen';
import { getClient } from '@/utils/client';
+import { store } from '@/utils/store';
import { useNotifications } from '@kadena/kode-ui/patterns';
import { useEffect, useState } from 'react';
import { useAccount } from './account';
@@ -22,8 +23,11 @@ export const useFreezeInvestor = () => {
const submit = async (
data: ISetAddressFrozenProps,
): Promise => {
+ if (!account) return;
try {
const tx = await setAddressFrozen(data, account!);
+ await store.setFrozenMessage(data);
+
const signedTransaction = await sign(tx);
if (!signedTransaction) return;
diff --git a/packages/apps/rwa-demo/src/services/batchSetAddressFrozen.ts b/packages/apps/rwa-demo/src/services/batchSetAddressFrozen.ts
index 223bc8fd24..336be0c381 100644
--- a/packages/apps/rwa-demo/src/services/batchSetAddressFrozen.ts
+++ b/packages/apps/rwa-demo/src/services/batchSetAddressFrozen.ts
@@ -7,6 +7,7 @@ import { Pact } from '@kadena/client';
export interface IBatchSetAddressFrozenProps {
investorAccounts: string[];
pause: boolean;
+ message?: string;
}
export const batchSetAddressFrozen = async (
diff --git a/packages/apps/rwa-demo/src/services/setAddressFrozen.ts b/packages/apps/rwa-demo/src/services/setAddressFrozen.ts
index a623b4e433..8d5bafb8eb 100644
--- a/packages/apps/rwa-demo/src/services/setAddressFrozen.ts
+++ b/packages/apps/rwa-demo/src/services/setAddressFrozen.ts
@@ -7,6 +7,7 @@ import { Pact } from '@kadena/client';
export interface ISetAddressFrozenProps {
investorAccount: string;
pause: boolean;
+ message?: string;
}
export const setAddressFrozen = async (
diff --git a/packages/apps/rwa-demo/src/utils/store/index.ts b/packages/apps/rwa-demo/src/utils/store/index.ts
index 9af1b168d3..c0a8430c27 100644
--- a/packages/apps/rwa-demo/src/utils/store/index.ts
+++ b/packages/apps/rwa-demo/src/utils/store/index.ts
@@ -1,6 +1,8 @@
import type { ITransaction } from '@/components/TransactionsProvider/TransactionsProvider';
import type { ICSVAccount } from '@/services/batchRegisterIdentity';
+import type { IBatchSetAddressFrozenProps } from '@/services/batchSetAddressFrozen';
import type { IRegisterIdentityProps } from '@/services/registerIdentity';
+import type { ISetAddressFrozenProps } from '@/services/setAddressFrozen';
import { get, off, onValue, ref, set } from 'firebase/database';
import { getAsset } from '../getAsset';
import { database } from './firebase';
@@ -59,7 +61,7 @@ const RWAStore = () => {
const data = snapshot.toJSON();
if (!data) return [];
return Object.entries(data).map(
- ([key, value]) => value,
+ ([key, value]) => value.account,
) as IRegisterIdentityProps[];
};
@@ -71,7 +73,9 @@ const RWAStore = () => {
const asset = getAssetFolder();
if (!asset) return;
- const snapshot = await get(ref(database, `${asset}/accounts/${account}`));
+ const snapshot = await get(
+ ref(database, `${asset}/accounts/${account}/account`),
+ );
return snapshot.toJSON() as IRegisterIdentityProps;
};
@@ -83,7 +87,7 @@ const RWAStore = () => {
const asset = getAssetFolder();
if (!asset) return;
- await set(ref(database, `${asset}/accounts/${accountName}`), {
+ await set(ref(database, `${asset}/accounts/${accountName}/account`), {
accountName,
alias: alias ?? '',
});
@@ -102,7 +106,7 @@ const RWAStore = () => {
const asset = getAssetFolder();
if (!asset) return;
- const accountRef = ref(database, `${asset}/accounts/${account}`);
+ const accountRef = ref(database, `${asset}/accounts/${account}/account`);
onValue(accountRef, async (snapshot) => {
const data = snapshot.toJSON();
@@ -124,7 +128,7 @@ const RWAStore = () => {
setDataCallback(
Object.entries(data).map(
- ([key, value]) => value,
+ ([key, value]) => value.account,
) as IRegisterIdentityProps[],
);
});
@@ -132,6 +136,42 @@ const RWAStore = () => {
return () => off(accountRef);
};
+ const getFrozenMessage = async (
+ account: string,
+ ): Promise => {
+ const asset = getAssetFolder();
+ if (!asset) return;
+
+ const snapshot = await get(
+ ref(database, `${asset}/accounts/${account}/frozenMessage`),
+ );
+
+ return snapshot.toJSON() as any;
+ };
+
+ const setFrozenMessage = async (data: ISetAddressFrozenProps) => {
+ const asset = getAssetFolder();
+ if (!asset) return;
+
+ await set(
+ ref(database, `${asset}/accounts/${data.investorAccount}/frozenMessage`),
+ data.message,
+ );
+ };
+
+ const setFrozenMessages = async (data: IBatchSetAddressFrozenProps) => {
+ const asset = getAssetFolder();
+ if (!asset) return;
+
+ return data.investorAccounts.map((account) =>
+ setFrozenMessage({
+ investorAccount: account,
+ pause: data.pause,
+ message: data.message,
+ }),
+ );
+ };
+
return {
addTransaction,
removeTransaction,
@@ -143,6 +183,9 @@ const RWAStore = () => {
getAccounts,
listenToAccount,
listenToAccounts,
+ setFrozenMessage,
+ setFrozenMessages,
+ getFrozenMessage,
};
};