Skip to content

Commit

Permalink
feat(rwa): able to change the asset contract (#2686)
Browse files Browse the repository at this point in the history
  • Loading branch information
sstraatemans authored Nov 22, 2024
1 parent 0f3479b commit 2237938
Show file tree
Hide file tree
Showing 28 changed files with 350 additions and 38 deletions.
2 changes: 2 additions & 0 deletions .changeset/itchy-zebras-cry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
2 changes: 2 additions & 0 deletions packages/apps/rwa-demo/src/app/(app)/SideBar.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { AssetSwitch } from '@/components/AssetSwitch/AssetSwitch';
import { useAccount } from '@/hooks/account';
import {
MonoApps,
Expand Down Expand Up @@ -64,6 +65,7 @@ export const SideBar: FC = () => {
/>
</>
}
appContext={<AssetSwitch />}
context={
<>
<SideBarItemsInline>
Expand Down
21 changes: 20 additions & 1 deletion packages/apps/rwa-demo/src/app/(app)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
'use client';
import { SideBarLayout } from '@kadena/kode-ui/patterns';

import { AssetForm } from '@/components/AssetSwitch/AssetForm';
import { SupplyCount } from '@/components/SupplyCount/SupplyCount';
import { Link, Stack } from '@kadena/kode-ui';
import { getAsset } from '@/utils/getAsset';
import { Heading, Link, Stack } from '@kadena/kode-ui';
import React from 'react';
import { KLogo } from './KLogo';
import { SideBar } from './SideBar';
Expand All @@ -12,6 +14,23 @@ const RootLayout = ({
}: Readonly<{
children: React.ReactNode;
}>) => {
if (!getAsset()) {
return (
<Stack
flexDirection="column"
width="100%"
alignItems="center"
justifyContent="center"
style={{ height: '100dvh' }}
>
<div>
<Heading>Add new asset</Heading>
<AssetForm />
</div>
</Stack>
);
}

return (
<SideBarLayout
logo={
Expand Down
2 changes: 2 additions & 0 deletions packages/apps/rwa-demo/src/app/(app)/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import { AgentRootPage } from '@/components/HomePage/AgentRootPage';
import { OwnerRootPage } from '@/components/HomePage/OwnerRootPage';
import { useAccount } from '@/hooks/account';
import { getAsset } from '@/utils/getAsset';

const Home = () => {
const { isAgent } = useAccount();

console.log('asset', getAsset());
return (
<>
{!isAgent && <OwnerRootPage />}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,86 @@
'use client';
import {
LOCALSTORAGE_ASSETS_KEY,
LOCALSTORAGE_ASSETS_SELECTED_KEY,
} from '@/constants';
import { usePaused } from '@/hooks/paused';
import { getFullAsset } from '@/utils/getAsset';
import { getLocalStorageKey } from '@/utils/getLocalStorageKey';
import { useRouter } from 'next/navigation';

import type { FC, PropsWithChildren } from 'react';
import { createContext, useState } from 'react';
import { createContext, useEffect, useState } from 'react';

interface IAsset {
export interface IAsset {
uuid: string;
name: string;
}

export interface IAssetContext {
asset?: IAsset;
assets: IAsset[];
paused: boolean;
setAsset: (asset: IAsset) => void;
}

export const AssetContext = createContext<IAssetContext>({
paused: true,
assets: [],
paused: false,
setAsset: () => {},
});

export const AssetProvider: FC<PropsWithChildren> = ({ children }) => {
const router = useRouter();
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const [asset, setAsset] = useState<IAsset>();
const [assets, setAssets] = useState<IAsset[]>([]);
const storageKey = getLocalStorageKey(LOCALSTORAGE_ASSETS_KEY) ?? '';
const selectedKey =
getLocalStorageKey(LOCALSTORAGE_ASSETS_SELECTED_KEY) ?? '';
const { paused } = usePaused();

const getAssets = () => {
const result = localStorage.getItem(storageKey);
setAssets(JSON.parse(result ?? '[]'));
router.refresh();
};

const storageListener = (event: StorageEvent | Event) => {
if (event.type !== storageKey && 'key' in event && event.key !== storageKey)
return;
getAssets();
};

const handleSelectAsset = (data: IAsset) => {
localStorage.setItem(selectedKey, JSON.stringify(data));
setAsset(data);

router.refresh();
};

useEffect(() => {
getAssets();
window.addEventListener(storageKey, storageListener);
window.addEventListener('storage', storageListener);

return () => {
window.removeEventListener(storageKey, storageListener);
window.removeEventListener('storage', storageListener);
};
}, []);

useEffect(() => {
const asset = getFullAsset();
setAsset(asset);
if (asset) {
return;
}
}, []);

return (
<AssetContext.Provider value={{ asset, paused }}>
<AssetContext.Provider
value={{ asset, assets, setAsset: handleSelectAsset, paused }}
>
{children}
</AssetContext.Provider>
);
Expand Down
98 changes: 98 additions & 0 deletions packages/apps/rwa-demo/src/components/AssetSwitch/AssetForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import { LOCALSTORAGE_ASSETS_KEY } from '@/constants';
import { getLocalStorageKey } from '@/utils/getLocalStorageKey';
import { MonoAdd, MonoEditNote, MonoRemove } from '@kadena/kode-icons';
import { Button, TextField } from '@kadena/kode-ui';
import { useNotifications } from '@kadena/kode-ui/patterns';
import type { ChangeEventHandler, FC, FormEventHandler } from 'react';
import { useRef, useState } from 'react';
import type { IAsset } from '../AssetProvider/AssetProvider';

interface IProps {
asset?: IAsset;
}

export const AssetForm: FC<IProps> = ({ asset }) => {
const ref = useRef<HTMLInputElement | null>(null);
const { addNotification } = useNotifications();
const [value, setValue] = useState(asset?.name ?? '');

const handleChange: ChangeEventHandler<HTMLInputElement> = (e) => {
setValue(e.currentTarget.value);
};

const handleRemove = (data: IAsset) => {
const key = getLocalStorageKey(LOCALSTORAGE_ASSETS_KEY);
const assets = JSON.parse(localStorage.getItem(key) ?? '[]').filter(
(a: IAsset) => a.uuid !== data.uuid,
);
localStorage.setItem(key, JSON.stringify(assets));
window.dispatchEvent(new Event(key));

addNotification({
label: 'Asset removed',
intent: 'negative',
});
};

const handleSave: FormEventHandler<HTMLFormElement> = () => {
const key = getLocalStorageKey(LOCALSTORAGE_ASSETS_KEY);
const assets = JSON.parse(localStorage.getItem(key) ?? '[]');

let newAssets = [...assets];
if (!asset) {
const newAsset = {
uuid: crypto.randomUUID(),
name: value,
};
newAssets.push(newAsset);

addNotification({
label: 'Asset added',
intent: 'positive',
});
} else {
newAssets = newAssets.map((v) => {
if (v.uuid === asset.uuid) {
return { ...v, name: value };
}
return v;
});

addNotification({
label: 'Asset Changed',
intent: 'positive',
});
}

setValue('');
localStorage.setItem(key, JSON.stringify(newAssets));
window.dispatchEvent(new Event(key));
};

return (
<form onSubmit={handleSave}>
<TextField
ref={ref}
value={value}
label="New"
isRequired
onChange={handleChange}
endAddon={
<>
<Button
type="submit"
isDisabled={!value}
endVisual={!asset ? <MonoAdd /> : <MonoEditNote />}
/>
{asset?.uuid && (
<Button
onPress={() => handleRemove(asset)}
endVisual={<MonoRemove />}
/>
)}
</>
}
/>
</form>
);
};
70 changes: 70 additions & 0 deletions packages/apps/rwa-demo/src/components/AssetSwitch/AssetSwitch.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import { useAsset } from '@/hooks/asset';
import { MonoSettings } from '@kadena/kode-icons';
import {
Button,
ContextMenu,
ContextMenuDivider,
ContextMenuItem,
} from '@kadena/kode-ui';
import {
RightAside,
RightAsideContent,
RightAsideHeader,
useLayout,
} from '@kadena/kode-ui/patterns';
import type { FC } from 'react';
import { useState } from 'react';
import { AssetForm } from './AssetForm';

export const AssetSwitch: FC = () => {
const { assets, asset, setAsset } = useAsset();
const [openSide, setOpenSide] = useState(false);
const { setIsRightAsideExpanded, isRightAsideExpanded } = useLayout();

return (
<>
{isRightAsideExpanded && openSide && (
<RightAside
isOpen
onClose={() => {
setIsRightAsideExpanded(false);
setOpenSide(false);
}}
>
<RightAsideHeader label="Assets" />
<RightAsideContent>
{assets.map((ass) => (
<AssetForm key={ass.uuid} asset={ass} />
))}
<AssetForm />
</RightAsideContent>
</RightAside>
)}
<ContextMenu
trigger={
<Button isCompact variant="outlined">
{asset ? asset.name : 'Select an asset'}
</Button>
}
>
{assets.map((ass) => (
<ContextMenuItem
onClick={() => setAsset(ass)}
key={ass.uuid}
label={ass.name}
/>
))}
<ContextMenuDivider />

<ContextMenuItem
onClick={() => {
setIsRightAsideExpanded(true);
setOpenSide(true);
}}
endVisual={<MonoSettings />}
label="Asset Settings"
/>
</ContextMenu>
</>
);
};
2 changes: 2 additions & 0 deletions packages/apps/rwa-demo/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export const ACCOUNT_COOKIE_NAME = 'spirekey';
export const LOCALSTORAGE_ASSETS_KEY = 'assets';
export const LOCALSTORAGE_ASSETS_SELECTED_KEY = 'selected_asset';

// todo: this is temporary for devnet
export const ADMIN = {
Expand Down
5 changes: 3 additions & 2 deletions packages/apps/rwa-demo/src/hooks/getAgents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { ITransaction } from '@/components/TransactionsProvider/Transaction
import { coreEvents } from '@/services/graph/agent.graph';
import type { IRecord } from '@/utils/filterRemovedRecords';
import { filterRemovedRecords } from '@/utils/filterRemovedRecords';
import { getAsset } from '@/utils/getAsset';
import type * as Apollo from '@apollo/client';
import { useEffect, useState } from 'react';
import { useTransactions } from './transactions';
Expand All @@ -27,13 +28,13 @@ export const useGetAgents = () => {
error,
} = useEventsQuery({
variables: {
qualifiedName: 'RWA.mvp-token.AGENT-ADDED',
qualifiedName: `RWA.${getAsset()}.AGENT-ADDED`,
},
});

const { data: removedData, loading: removedLoading } = useEventsQuery({
variables: {
qualifiedName: 'RWA.mvp-token.AGENT-REMOVED',
qualifiedName: `RWA.${getAsset()}.AGENT-REMOVED`,
},
});

Expand Down
5 changes: 3 additions & 2 deletions packages/apps/rwa-demo/src/hooks/getInvestors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { ITransaction } from '@/components/TransactionsProvider/Transaction
import { coreEvents } from '@/services/graph/agent.graph';
import type { IRecord } from '@/utils/filterRemovedRecords';
import { filterRemovedRecords } from '@/utils/filterRemovedRecords';
import { getAsset } from '@/utils/getAsset';
import type * as Apollo from '@apollo/client';
import { useEffect, useState } from 'react';
import { useTransactions } from './transactions';
Expand All @@ -27,13 +28,13 @@ export const useGetInvestors = () => {
error,
} = useEventsQuery({
variables: {
qualifiedName: 'RWA.mvp-token.IDENTITY-REGISTERED',
qualifiedName: `RWA.${getAsset()}.IDENTITY-REGISTERED`,
},
});

const { data: removedData, loading: removedLoading } = useEventsQuery({
variables: {
qualifiedName: 'RWA.mvp-token.IDENTITY-REMOVED',
qualifiedName: `RWA.${getAsset()}.IDENTITY-REMOVED`,
},
});

Expand Down
Loading

0 comments on commit 2237938

Please sign in to comment.