Skip to content

Commit

Permalink
partially freeze investor tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
sstraatemans committed Dec 3, 2024
1 parent 60919be commit 798b899
Show file tree
Hide file tree
Showing 5 changed files with 213 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { DistributionForm } from '@/components/DistributionForm/DistributionForm';
import { FreezeInvestor } from '@/components/FreezeInvestor/FreezeInvestor';
import { InvestorInfo } from '@/components/InvestorInfo/InvestorInfo';
import { PartiallyFreezeTokensForm } from '@/components/PartiallyFreezeTokensForm/PartiallyFreezeTokensForm';
import { SideBarBreadcrumbs } from '@/components/SideBarBreadcrumbs/SideBarBreadcrumbs';
import { useAsset } from '@/hooks/asset';
import { useFreeze } from '@/hooks/freeze';
Expand All @@ -17,13 +18,19 @@ const InvestorPage = () => {
const { paused } = useAsset();
const params = useParams();
const [hasOpenDistributeForm, setHasOpenDistributeForm] = useState(false);
const [hasOpenPartiallyFreezeForm, setHasOpenPartiallyFreezeForm] =
useState(false);
const investorAccount = decodeURIComponent(params.investorAccount as string);
const { frozen } = useFreeze({ investorAccount });

const handleDistributeTokens = () => {
setIsRightAsideExpanded(true);
setHasOpenDistributeForm(true);
};
const handlePartiallyFreezeTokens = () => {
setIsRightAsideExpanded(true);
setHasOpenPartiallyFreezeForm(true);
};

return (
<>
Expand All @@ -42,6 +49,15 @@ const InvestorPage = () => {
}}
/>
)}
{isRightAsideExpanded && hasOpenPartiallyFreezeForm && (
<PartiallyFreezeTokensForm
investorAccount={investorAccount}
onClose={() => {
setIsRightAsideExpanded(false);
setHasOpenPartiallyFreezeForm(false);
}}
/>
)}

<Stack width="100%" flexDirection="column">
<InvestorInfo investorAccount={investorAccount} />
Expand All @@ -54,6 +70,14 @@ const InvestorPage = () => {
Distribute Tokens
</Button>

<Button
startVisual={<MonoAdd />}
onPress={handlePartiallyFreezeTokens}
isDisabled={frozen || paused}
>
Partially freeze tokens
</Button>

<FreezeInvestor investorAccount={investorAccount} />
</Stack>
</Stack>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useAccount } from '@/hooks/account';
import { useFreeze } from '@/hooks/freeze';
import { MonoCompareArrows } from '@kadena/kode-icons';
import { Button, Stack } from '@kadena/kode-ui';
import { useLayout } from '@kadena/kode-ui/patterns';
Expand All @@ -8,7 +9,8 @@ import { InvestorInfo } from '../InvestorInfo/InvestorInfo';
import { TransferForm } from '../TransferForm/TransferForm';

export const InvestorRootPage: FC = () => {
const { isInvestor, account, isFrozen } = useAccount();
const { isInvestor, account } = useAccount();
const { frozen } = useFreeze({ investorAccount: account?.address! });
const { setIsRightAsideExpanded, isRightAsideExpanded } = useLayout();
const [hasOpenTransferForm, setHasOpenTransferForm] = useState(false);

Expand Down Expand Up @@ -37,7 +39,7 @@ export const InvestorRootPage: FC = () => {
<Button
startVisual={<MonoCompareArrows />}
onPress={handleTransferTokens}
isDisabled={isFrozen}
isDisabled={frozen}
>
Transfer tokens
</Button>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { useAccount } from '@/hooks/account';
import { useAsset } from '@/hooks/asset';
import { useFreeze } from '@/hooks/freeze';
import { usePartiallyFreezeTokens } from '@/hooks/partiallyFreezeTokens';
import type { IPartiallyFreezeTokensProps } from '@/services/partiallyFreezeTokens';
import { Button, TextField } from '@kadena/kode-ui';
import {
RightAside,
RightAsideContent,
RightAsideFooter,
RightAsideHeader,
} from '@kadena/kode-ui/patterns';
import type { FC } from 'react';
import { useEffect, useRef, useState } from 'react';
import { useForm } from 'react-hook-form';
import { AssetPausedMessage } from '../AssetPausedMessage/AssetPausedMessage';
import { InvestorFrozenMessage } from '../InvestorFrozenMessage/InvestorFrozenMessage';
import { SendTransactionAnimation } from '../SendTransactionAnimation/SendTransactionAnimation';
import type { ITransaction } from '../TransactionsProvider/TransactionsProvider';

interface IProps {
onClose: () => void;
investorAccount: string;
}

export const PartiallyFreezeTokensForm: FC<IProps> = ({
onClose,
investorAccount,
}) => {
const { frozen } = useFreeze({ investorAccount });
const [tx, setTx] = useState<ITransaction>();
const resolveRef = useRef<Function | null>(null);
const { paused } = useAsset();

const { submit } = usePartiallyFreezeTokens();
const { register, handleSubmit } = useForm<IPartiallyFreezeTokensProps>({
values: {
amount: 0,
investorAccount,
},
});

const onSubmit = async (data: IPartiallyFreezeTokensProps) => {
const transaction = await submit(data);
setTx(transaction);

return transaction;
};

useEffect(() => {
if (tx && resolveRef.current) {
resolveRef.current(tx);
onClose();
}
}, [tx]);

const waitForStateChange = () => {
return new Promise((resolve) => {
resolveRef.current = resolve;
});
};

const handlePress = async () => {
const message = await waitForStateChange();
return message;
};

return (
<>
<RightAside isOpen onClose={onClose}>
<form onSubmit={handleSubmit(onSubmit)}>
<RightAsideHeader label="Partially Freeze Tokens" />
<RightAsideContent>
<TextField
label="Amount"
type="number"
{...register('amount', { required: true })}
/>
</RightAsideContent>
<RightAsideFooter
message={
<>
<InvestorFrozenMessage investorAccount={investorAccount} />
<AssetPausedMessage />
</>
}
>
<Button onPress={onClose} variant="transparent">
Cancel
</Button>
<SendTransactionAnimation
onPress={handlePress}
trigger={
<Button isDisabled={frozen || paused} type="submit">
Distribute
</Button>
}
/>
</RightAsideFooter>
</form>
</RightAside>
</>
);
};
39 changes: 39 additions & 0 deletions packages/apps/rwa-demo/src/hooks/partiallyFreezeTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { interpretErrorMessage } from '@/components/TransactionsProvider/TransactionsProvider';
import type { IDistributeTokensProps } from '@/services/distributeTokens';
import { distributeTokens } from '@/services/distributeTokens';
import { partiallyFreezeTokens } from '@/services/partiallyFreezeTokens';
import { getClient } from '@/utils/client';
import { useNotifications } from '@kadena/kode-ui/patterns';
import { useAccount } from './account';
import { useTransactions } from './transactions';

export const usePartiallyFreezeTokens = () => {
const { account, sign } = useAccount();
const { addTransaction } = useTransactions();
const { addNotification } = useNotifications();

const submit = async (data: IDistributeTokensProps) => {
try {
const tx = await partiallyFreezeTokens(data, account!);

const signedTransaction = await sign(tx);
if (!signedTransaction) return;

const client = getClient();
const res = await client.submit(signedTransaction);

return addTransaction({
...res,
type: 'PARTIALLYFREEZETOKENS',
});
} catch (e: any) {
addNotification({
intent: 'negative',
label: 'there was an error',
message: interpretErrorMessage(e.message),
});
}
};

return { submit };
};
42 changes: 42 additions & 0 deletions packages/apps/rwa-demo/src/services/partiallyFreezeTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import type { IWalletAccount } from '@/components/AccountProvider/utils';
import { getNetwork } from '@/utils/client';
import { env } from '@/utils/env';
import { getAsset } from '@/utils/getAsset';
import { Pact } from '@kadena/client';
import { PactNumber } from '@kadena/pactjs';

export interface IPartiallyFreezeTokensProps {
amount: number;
investorAccount: string;
}

const createPubKeyFromAccount = (account: string): string => {
return account.replace('k:', '').replace('r:', '');
};

export const partiallyFreezeTokens = async (
data: IPartiallyFreezeTokensProps,
account: IWalletAccount,
) => {
return Pact.builder
.execution(
`
(RWA.${getAsset()}.freeze-partial-tokens (read-string 'investor) ${new PactNumber(data.amount).toDecimal()})`,
)
.addData('agent', account.address)
.addData('investor', data.investorAccount)
.addData('investor-keyset', {
keys: [createPubKeyFromAccount(data.investorAccount)],
pred: 'keys-all',
})
.setMeta({
senderAccount: account.address,
chainId: getNetwork().chainId,
})
.addSigner(account.keyset.guard.keys[0], (withCap) => [
withCap(`RWA.${getAsset()}.ONLY-AGENT`, 'freezer'),
withCap(`coin.GAS`),
])
.setNetworkId(getNetwork().networkId)
.createTransaction();
};

0 comments on commit 798b899

Please sign in to comment.