diff --git a/packages/apps/dev-wallet/src/Components/SideBarBreadcrumbs/SideBarBreadcrumbs.tsx b/packages/apps/dev-wallet/src/Components/SideBarBreadcrumbs/SideBarBreadcrumbs.tsx index 8ca58af559..381b0c92e2 100644 --- a/packages/apps/dev-wallet/src/Components/SideBarBreadcrumbs/SideBarBreadcrumbs.tsx +++ b/packages/apps/dev-wallet/src/Components/SideBarBreadcrumbs/SideBarBreadcrumbs.tsx @@ -11,16 +11,18 @@ export const SideBarBreadcrumbs: FC = ({ const { activeNetwork } = useWallet(); return ( - - <> + {`${activeNetwork?.name}`} - {React.Children.map(children, (child) => { - if (!React.isValidElement(child)) { - return null; - } - return React.cloneElement(child, { ...child.props, component: Link }); - })} - + } + > + {React.Children.map(children, (child) => { + if (!React.isValidElement(child)) { + return null; + } + return React.cloneElement(child, { ...child.props, component: Link }); + })} ); }; diff --git a/packages/apps/proof-of-us/src/components/AccountProvider/AccountProvider.tsx b/packages/apps/proof-of-us/src/components/AccountProvider/AccountProvider.tsx index e28d534e42..ae5b305377 100644 --- a/packages/apps/proof-of-us/src/components/AccountProvider/AccountProvider.tsx +++ b/packages/apps/proof-of-us/src/components/AccountProvider/AccountProvider.tsx @@ -2,7 +2,7 @@ import { env } from '@/utils/env'; import { getAccountCookieName } from '@/utils/getAccountCookieName'; import { store } from '@/utils/socket/store'; -import { connect, initSpireKey } from '@kadena/spirekey-sdk'; +import { connect } from '@kadena/spirekey-sdk'; import { useRouter } from 'next/navigation'; import type { FC, PropsWithChildren } from 'react'; import { createContext, useCallback, useEffect, useState } from 'react'; @@ -59,9 +59,6 @@ export const AccountProvider: FC = ({ children }) => { } } - initSpireKey({ - hostUrl: process.env.NEXT_PUBLIC_WALLET_URL, - }); setIsMounted(true); }, []); diff --git a/packages/apps/rwa-demo/.eslintrc.js b/packages/apps/rwa-demo/.eslintrc.js index 4e4a5d9190..546247d253 100644 --- a/packages/apps/rwa-demo/.eslintrc.js +++ b/packages/apps/rwa-demo/.eslintrc.js @@ -14,5 +14,6 @@ module.exports = { '@rushstack/no-new-null': 'off', 'react/react-in-jsx-scope': 'off', 'react/jsx-uses-react': 'off', + '@typescript-eslint/strict-boolean-expressions': 'off', }, }; diff --git a/packages/apps/rwa-demo/package.json b/packages/apps/rwa-demo/package.json index a83d7070c0..620b04e6e8 100644 --- a/packages/apps/rwa-demo/package.json +++ b/packages/apps/rwa-demo/package.json @@ -5,6 +5,7 @@ "scripts": { "build": "next build", "dev": "next dev", + "generate": "pactjs contract-generate --contract \"RWA.agent-role\" --chain 0 --network development --api \"http://localhost:8080/chainweb/0.0/development/chain/0/pact\"", "lint": "pnpm run /^lint:.*/", "lint:fmt": "prettier . --cache --check", "lint:src": "eslint src", @@ -14,9 +15,12 @@ "test:watch": "vitest --coverage" }, "dependencies": { + "@hookform/resolvers": "^3.2.0", "@kadena/client": "^1.15.0", + "@kadena/cryptography-utils": "workspace:*", "@kadena/kode-icons": "workspace:*", "@kadena/kode-ui": "workspace:*", + "@kadena/pactjs": "workspace:*", "@kadena/spirekey-sdk": "^1.0.0", "@vanilla-extract/css": "1.14.2", "@vanilla-extract/css-utils": "^0.1.3", @@ -26,12 +30,16 @@ "next": "14.2.2", "next-themes": "^0.2.1", "react": "^18.2.0", - "react-dom": "^18.2.0" + "react-dom": "^18.2.0", + "react-hook-form": "^7.45.4" }, "devDependencies": { "@kadena-dev/eslint-config": "workspace:*", "@kadena-dev/lint-package": "workspace:*", "@kadena-dev/shared-config": "workspace:*", + "@kadena/pactjs": "workspace:*", + "@kadena/pactjs-cli": "^1.15.0", + "@kadena/pactjs-generator": "workspace:*", "@types/node": "^20.12.7", "@types/react": "^18.2.79", "@types/react-dom": "^18.2.25", diff --git a/packages/apps/rwa-demo/src/app/(app)/page.tsx b/packages/apps/rwa-demo/src/app/(app)/page.tsx index 39c6194e26..4f4af003c8 100644 --- a/packages/apps/rwa-demo/src/app/(app)/page.tsx +++ b/packages/apps/rwa-demo/src/app/(app)/page.tsx @@ -1,7 +1,57 @@ 'use client'; +import { AddAgentForm } from '@/components/AddAgentForm/AddAgentForm'; +import { InitTokenForm } from '@/components/InitTokenForm/InitTokenForm'; +import { SideBarBreadcrumbs } from '@/components/SideBarBreadcrumbs/SideBarBreadcrumbs'; +import { MonoAdd } from '@kadena/kode-icons'; +import { Button } from '@kadena/kode-ui'; +import { SideBarBreadcrumbsItem, useLayout } from '@kadena/kode-ui/patterns'; +import { useState } from 'react'; const Home = () => { - return
Hello world
; + const { setIsRightAsideExpanded, isRightAsideExpanded } = useLayout(); + const [hasOpenInitForm, setHasOpenInitForm] = useState(false); + const [hasOpenAgentForm, setHasOpenAgentForm] = useState(false); + + const handleAddAgent = () => { + setIsRightAsideExpanded(true); + setHasOpenAgentForm(true); + }; + + const handleInitToken = () => { + setIsRightAsideExpanded(true); + setHasOpenInitForm(true); + }; + + return ( +
+ + Tokens + + {isRightAsideExpanded && hasOpenAgentForm && ( + { + setIsRightAsideExpanded(false); + setHasOpenAgentForm(false); + }} + /> + )} + {isRightAsideExpanded && hasOpenInitForm && ( + { + setIsRightAsideExpanded(false); + setHasOpenInitForm(false); + }} + /> + )} + + + +
+ ); }; export default Home; diff --git a/packages/apps/rwa-demo/src/app/Providers.tsx b/packages/apps/rwa-demo/src/app/Providers.tsx index cfc75e85ae..e0ed01ff47 100644 --- a/packages/apps/rwa-demo/src/app/Providers.tsx +++ b/packages/apps/rwa-demo/src/app/Providers.tsx @@ -1,4 +1,6 @@ import { AccountProvider } from '@/components/AccountProvider/AccountProvider'; +import { AssetProvider } from '@/components/AssetProvider/AssetProvider'; +import { NetworkProvider } from '@/components/NetworkProvider/NetworkProvider'; import { MediaContextProvider } from '@kadena/kode-ui'; import { LayoutProvider } from '@kadena/kode-ui/patterns'; import { darkThemeClass } from '@kadena/kode-ui/styles'; @@ -10,7 +12,6 @@ export const Providers: FC = ({ children }) => { = ({ children }) => { enableSystem={true} enableColorScheme={true} // When enabled, we can't make the background of the embedded iframe transparent > - - {children} - + + + + {children} + + + ); diff --git a/packages/apps/rwa-demo/src/components/AccountProvider/AccountProvider.tsx b/packages/apps/rwa-demo/src/components/AccountProvider/AccountProvider.tsx index 39a9c022bf..ed84ebfde1 100644 --- a/packages/apps/rwa-demo/src/components/AccountProvider/AccountProvider.tsx +++ b/packages/apps/rwa-demo/src/components/AccountProvider/AccountProvider.tsx @@ -52,6 +52,7 @@ export const AccountProvider: FC = ({ children }) => { useEffect(() => { const storage = localStorage.getItem(getAccountCookieName()); if (storage) { + console.log({ account: JSON.parse(storage) }); try { setAccount(JSON.parse(storage)); } catch (e) { diff --git a/packages/apps/rwa-demo/src/components/AddAgentForm/AddAgentForm.tsx b/packages/apps/rwa-demo/src/components/AddAgentForm/AddAgentForm.tsx new file mode 100644 index 0000000000..7bfe82ddf5 --- /dev/null +++ b/packages/apps/rwa-demo/src/components/AddAgentForm/AddAgentForm.tsx @@ -0,0 +1,64 @@ +import { useAccount } from '@/hooks/account'; +import { useNetwork } from '@/hooks/networks'; +import type { IAddAgentProps } from '@/services/addAgent'; +import { addAgent } from '@/services/addAgent'; +import { Button, TextField } from '@kadena/kode-ui'; +import { + RightAside, + RightAsideContent, + RightAsideFooter, + RightAsideHeader, +} from '@kadena/kode-ui/patterns'; +import type { FC } from 'react'; +import { useState } from 'react'; +import { useForm } from 'react-hook-form'; + +interface IProps { + onClose: () => void; +} + +export const AddAgentForm: FC = ({ onClose }) => { + const { activeNetwork } = useNetwork(); + const { account } = useAccount(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [_, setError] = useState(null); + const { register, handleSubmit } = useForm({ + defaultValues: { + agent: '', + }, + }); + + const onSubmit = async (data: IAddAgentProps) => { + console.log({ data }); + setError(null); + try { + await addAgent(data, activeNetwork, account!); + + // setIsRightAsideExpanded(false); + } catch (e: any) { + setError(e?.message || e); + } + + // onClose(); + }; + + return ( + +
+ + + + + + + + + +
+ ); +}; diff --git a/packages/apps/rwa-demo/src/components/AssetProvider/AssetProvider.tsx b/packages/apps/rwa-demo/src/components/AssetProvider/AssetProvider.tsx new file mode 100644 index 0000000000..904b3e11b6 --- /dev/null +++ b/packages/apps/rwa-demo/src/components/AssetProvider/AssetProvider.tsx @@ -0,0 +1,22 @@ +'use client'; +import type { FC, PropsWithChildren } from 'react'; +import { createContext, useState } from 'react'; + +interface IAsset { + name: string; +} + +export interface IAssetContext { + asset?: IAsset; +} + +export const AssetContext = createContext({}); + +export const AssetProvider: FC = ({ children }) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [asset, setAsset] = useState(); + + return ( + {children} + ); +}; diff --git a/packages/apps/rwa-demo/src/components/InitTokenForm/InitTokenForm.tsx b/packages/apps/rwa-demo/src/components/InitTokenForm/InitTokenForm.tsx new file mode 100644 index 0000000000..1763a8fc43 --- /dev/null +++ b/packages/apps/rwa-demo/src/components/InitTokenForm/InitTokenForm.tsx @@ -0,0 +1,68 @@ +import { useAccount } from '@/hooks/account'; +import { useNetwork } from '@/hooks/networks'; +import type { IInitTokenProps } from '@/services/initToken'; +import { initToken } from '@/services/initToken'; +import { Button, TextField } from '@kadena/kode-ui'; +import { + RightAside, + RightAsideContent, + RightAsideFooter, + RightAsideHeader, +} from '@kadena/kode-ui/patterns'; +import type { FC } from 'react'; +import { useState } from 'react'; +import { useForm } from 'react-hook-form'; + +interface IProps { + onClose: () => void; +} + +export const InitTokenForm: FC = ({ onClose }) => { + const { activeNetwork } = useNetwork(); + const { account } = useAccount(); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [error, setError] = useState(null); + const { register, handleSubmit } = useForm({ + defaultValues: { + name: '', + }, + }); + + const onSubmit = async (data: IInitTokenProps) => { + console.log({ data }); + setError(null); + //try { + await initToken(data, activeNetwork, account!); + + //onClose(); + // setIsRightAsideExpanded(false); + // } catch (e: any) { + // setError(e?.message || e); + // } + }; + + return ( + +
+ + + + + + + + + + + +
+ ); +}; diff --git a/packages/apps/rwa-demo/src/components/NetworkProvider/NetworkProvider.tsx b/packages/apps/rwa-demo/src/components/NetworkProvider/NetworkProvider.tsx new file mode 100644 index 0000000000..9ad2b1322e --- /dev/null +++ b/packages/apps/rwa-demo/src/components/NetworkProvider/NetworkProvider.tsx @@ -0,0 +1,61 @@ +'use client'; +import { env } from '@/utils/env'; +import type { ChainId } from '@kadena/client'; +import type { FC, PropsWithChildren } from 'react'; +import { createContext, useState } from 'react'; + +export interface INetwork { + name: string; + networkId: string; + host: string; + chainId: ChainId; +} + +export interface INetworkContext { + activeNetwork: INetwork; + networks: INetwork[]; +} + +const defaultContext: INetworkContext = { + activeNetwork: { + name: env.NETWORKNAME, + networkId: env.NETWORKID, + host: env.NETWORKHOST, + chainId: env.CHAINID, + }, + networks: [ + { + networkId: 'testnet05', + name: 'Testnet(Pact5)', + host: 'https://api.testnet05.chainweb.com', + chainId: '0', + }, + { + networkId: 'testnet04', + name: 'Testnet', + host: 'https://api.testnet.chainweb.com', + chainId: '0', + }, + { + networkId: 'development', + name: 'development', + host: 'https://localhost:8080', + chainId: '0', + }, + ], +}; + +export const NetworkContext = createContext(defaultContext); + +export const NetworkProvider: FC = ({ children }) => { + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const [activeNetwork, _] = useState(defaultContext.activeNetwork); + + return ( + + {children} + + ); +}; diff --git a/packages/apps/rwa-demo/src/components/SideBarBreadcrumbs/SideBarBreadcrumbs.tsx b/packages/apps/rwa-demo/src/components/SideBarBreadcrumbs/SideBarBreadcrumbs.tsx new file mode 100644 index 0000000000..b4bb1b3af7 --- /dev/null +++ b/packages/apps/rwa-demo/src/components/SideBarBreadcrumbs/SideBarBreadcrumbs.tsx @@ -0,0 +1,38 @@ +import { useNetwork } from '@/hooks/networks'; +import type { IBreadcrumbsProps } from '@kadena/kode-ui'; +import { Badge } from '@kadena/kode-ui'; +import { + SideBarBreadcrumbsItem, + SideBarBreadcrumbs as SideBarBreadcrumbsUI, +} from '@kadena/kode-ui/patterns'; +import Link from 'next/link'; +import type { FC } from 'react'; +import React from 'react'; + +export const SideBarBreadcrumbs: FC = ({ + children, + ...props +}) => { + const { activeNetwork } = useNetwork(); + + return ( + {`${activeNetwork?.name}`} + } + > + <> + + Dashboard + + {React.Children.map(children, (child) => { + if (!React.isValidElement(child)) { + return null; + } + return React.cloneElement(child, { ...child.props, component: Link }); + })} + + + ); +}; diff --git a/packages/apps/rwa-demo/src/constants.ts b/packages/apps/rwa-demo/src/constants.ts index 6ed3902caf..b9828b58e6 100644 --- a/packages/apps/rwa-demo/src/constants.ts +++ b/packages/apps/rwa-demo/src/constants.ts @@ -1 +1,7 @@ export const ACCOUNT_COOKIE_NAME = 'spirekey'; + +// todo: this is temporary for devnet +export const ADMIN = { + account: 'k:dd127c8553f430849069ba54e4edc3bf5e8ed0cfa62b33b37da6ee638cb79e55', + publicKey: 'dd127c8553f430849069ba54e4edc3bf5e8ed0cfa62b33b37da6ee638cb79e55', +}; diff --git a/packages/apps/rwa-demo/src/hooks/asset.ts b/packages/apps/rwa-demo/src/hooks/asset.ts new file mode 100644 index 0000000000..faf3054e91 --- /dev/null +++ b/packages/apps/rwa-demo/src/hooks/asset.ts @@ -0,0 +1,6 @@ +import type { IAssetContext } from '@/components/AssetProvider/AssetProvider'; +import { AssetContext } from '@/components/AssetProvider/AssetProvider'; + +import { useContext } from 'react'; + +export const useAsset = (): IAssetContext => useContext(AssetContext); diff --git a/packages/apps/rwa-demo/src/hooks/networks.ts b/packages/apps/rwa-demo/src/hooks/networks.ts new file mode 100644 index 0000000000..449b61b3c1 --- /dev/null +++ b/packages/apps/rwa-demo/src/hooks/networks.ts @@ -0,0 +1,6 @@ +import type { INetworkContext } from '@/components/NetworkProvider/NetworkProvider'; +import { NetworkContext } from '@/components/NetworkProvider/NetworkProvider'; + +import { useContext } from 'react'; + +export const useNetwork = (): INetworkContext => useContext(NetworkContext); diff --git a/packages/apps/rwa-demo/src/services/addAgent.ts b/packages/apps/rwa-demo/src/services/addAgent.ts new file mode 100644 index 0000000000..1809f29b96 --- /dev/null +++ b/packages/apps/rwa-demo/src/services/addAgent.ts @@ -0,0 +1,65 @@ +import type { INetwork } from '@/components/NetworkProvider/NetworkProvider'; +import { ADMIN } from '@/constants'; +import { Pact } from '@kadena/client'; +import type { ConnectedAccount } from '@kadena/spirekey-sdk'; + +export interface IAddAgentProps { + agent: string; +} + +const createPubKeyFromAccount = (account: string): string => { + return account.replace('k:', '').replace('r:', ''); +}; + +// const doSubmit = async (txArg: any) => { +// const client = getClient(); + +// // try { +// console.log(1); +// const res = await client.submit(txArg); +// console.log({ res }); +// // return; +// // } catch (err: any) { +// // console.log(err); +// // } +// }; + +export const addAgent = async ( + data: IAddAgentProps, + network: INetwork, + account: ConnectedAccount, +) => { + const transaction = Pact.builder + .execution( + `(RWA.agent-role.add-agent (read-string 'agent) (read-keyset 'agent_guard))`, + ) + .setMeta({ + senderAccount: ADMIN.account, + chainId: network.chainId, + }) + .addSigner(ADMIN.publicKey, (withCap) => [ + withCap(`RWA.agent-role.ONLY-OWNER`), + withCap(`coin.GAS`), + ]) + .addData('agent', data.agent) + .addData('agent_guard', { + keys: [createPubKeyFromAccount(data.agent)], + pred: 'keys-all', + }) + + .setNetworkId(network.networkId) + .createTransaction(); + + console.log({ transaction }); + console.log(transaction.cmd); + console.log(JSON.parse(transaction.cmd)); + + // const { transactions, isReady } = await sign([transaction], [account]); + // await isReady(); + // console.log(transactions); + + // eslint-disable-next-line @typescript-eslint/no-floating-promises + // transactions.map(async (t) => { + // await doSubmit(t); + // }); +}; diff --git a/packages/apps/rwa-demo/src/services/getAccount.ts b/packages/apps/rwa-demo/src/services/getAccount.ts new file mode 100644 index 0000000000..3b5fb98cb8 --- /dev/null +++ b/packages/apps/rwa-demo/src/services/getAccount.ts @@ -0,0 +1,22 @@ +import type { INetwork } from '@/components/NetworkProvider/NetworkProvider'; +import { getClient } from '@/utils/client'; +import { Pact } from '@kadena/client'; + +export const getAccount = async (accountId: string, network: INetwork) => { + const client = getClient(); + + const transaction = Pact.builder + .execution(`(coin.details "${accountId}")`) + .setMeta({ + chainId: network.chainId, + }) + .setNetworkId(network.networkId) + .createTransaction(); + + const { result } = await client.local(transaction, { + preflight: false, + signatureVerification: false, + }); + + return result.status === 'success' ? result.data : undefined; +}; diff --git a/packages/apps/rwa-demo/src/services/initToken.ts b/packages/apps/rwa-demo/src/services/initToken.ts new file mode 100644 index 0000000000..f8fe514052 --- /dev/null +++ b/packages/apps/rwa-demo/src/services/initToken.ts @@ -0,0 +1,73 @@ +import type { INetwork } from '@/components/NetworkProvider/NetworkProvider'; +import { ADMIN } from '@/constants'; +import { getPubKey } from '@/utils/getPubKey'; +import { Pact } from '@kadena/client'; +import type { ConnectedAccount } from '@kadena/spirekey-sdk'; +import { sign } from '@kadena/spirekey-sdk'; + +export interface IInitTokenProps { + name: string; + symbol: string; + kadenaId: string; +} + +// const doSubmit = async (txArg: any) => { +// const client = getClient(); + +// // try { +// console.log(1); + +// const res = await client.submit(txArg); +// console.log({ res }); +// // return; +// // } catch (err: any) { +// // console.log(err); +// // } +// }; + +export const initToken = async ( + data: IInitTokenProps, + network: INetwork, + owner: ConnectedAccount, +) => { + console.log({ owner }); + const transaction = Pact.builder + .execution( + ` + (RWA.agent-role.init (read-keyset 'owner_guard)) + (RWA.identity-registry.init RWA.agent-role) + (RWA.mvp-token.init "mvp-token2" "MVP2" 0 "kadenaID2" "0.0" RWA.agent-role RWA.max-balance-compliance RWA.identity-registry false) + (RWA.max-balance-compliance.init) + `, + ) + .setMeta({ + senderAccount: owner.accountName, + chainId: network.chainId, + }) + .addSigner( + { + pubKey: getPubKey(owner!), + scheme: 'WebAuthn', + }, + (withCap) => [], + ) + .addSigner(ADMIN.publicKey, (withCap) => []) + .addData('owner_guard', { + keys: [ADMIN.publicKey], + pred: 'keys-all', + }) + .setNetworkId(network.networkId) + .createTransaction(); + + console.log({ transaction }); + console.log({ cmd: JSON.parse(transaction.cmd) }); + const { transactions } = await sign([transaction], [owner]); + // console.log(res); + console.log({ transactions }); + // transactions.map(async (t) => { + // // should perform check to see if all sigs are present + + // console.log({ t }); + // await doSubmit(t); + // }); +}; diff --git a/packages/apps/rwa-demo/src/utils/client.ts b/packages/apps/rwa-demo/src/utils/client.ts new file mode 100644 index 0000000000..723b3db67d --- /dev/null +++ b/packages/apps/rwa-demo/src/utils/client.ts @@ -0,0 +1,7 @@ +import { createClient } from '@kadena/client'; +import { env } from './env'; + +export const getClient = (url?: string) => { + const client = createClient(url ? url : env.CHAINWEBAPIURL); + return client; +}; diff --git a/packages/apps/rwa-demo/src/utils/env.ts b/packages/apps/rwa-demo/src/utils/env.ts index 2dcce9fda0..52ad5e0931 100644 --- a/packages/apps/rwa-demo/src/utils/env.ts +++ b/packages/apps/rwa-demo/src/utils/env.ts @@ -5,20 +5,26 @@ const WALLET_URL = process.env.NEXT_PUBLIC_WALLET_URL; const CHAINID = process.env.NEXT_PUBLIC_CHAINID; const NETWORKID = process.env.NEXT_PUBLIC_NETWORKID; const NETWORKNAME = process.env.NEXT_PUBLIC_NETWORKNAME; +const NETWORKHOST = process.env.NEXT_PUBLIC_NETWORKHOST; const CHAINWEBAPIURL = process.env.NEXT_PUBLIC_CHAINWEBAPIURL; +const ACCOUNT = process.env.NEXT_PUBLIC_ACCOUNT; if (!WALLET_URL) console.error('NEXT_PUBLIC_WALLET_URL is not set'); if (!URL) console.error('NEXT_PUBLIC_URL is not set'); if (!CHAINID) console.error('NEXT_PUBLIC_CHAINID is not set'); if (!NETWORKID) console.error('NEXT_PUBLIC_NETWORKID is not set'); if (!NETWORKNAME) console.error('NEXT_PUBLIC_NETWORKNAME is not set'); +if (!NETWORKHOST) console.error('NEXT_PUBLIC_NETWORKHOST is not set'); if (!CHAINWEBAPIURL) console.error('NEXT_PUBLIC_CHAINWEBAPIURL is not set'); +if (!ACCOUNT) console.error('NEXT_PUBLIC_ACCOUNT is not set'); export const env = { WALLET_URL, URL, CHAINID: (CHAINID ?? '1') as ChainId, NETWORKID: NETWORKID ?? 'testnet04', - NETWORKNAME, - CHAINWEBAPIURL: CHAINWEBAPIURL, -}; + NETWORKNAME: NETWORKNAME ?? '', + NETWORKHOST: NETWORKHOST ?? '', + CHAINWEBAPIURL: CHAINWEBAPIURL ?? '', + ACCOUNTID: ACCOUNT, +} as const; diff --git a/packages/apps/rwa-demo/src/utils/getPubKey.ts b/packages/apps/rwa-demo/src/utils/getPubKey.ts new file mode 100644 index 0000000000..423d836c1a --- /dev/null +++ b/packages/apps/rwa-demo/src/utils/getPubKey.ts @@ -0,0 +1,5 @@ +import type { ConnectedAccount } from '@kadena/spirekey-sdk'; + +export const getPubKey = (account: ConnectedAccount) => { + return account.keyset?.keys.find((key) => key.includes('WEBAUTHN-')) ?? ''; +}; diff --git a/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.css.ts b/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.css.ts index dca92a4206..003b7ebaed 100644 --- a/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.css.ts +++ b/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.css.ts @@ -8,6 +8,7 @@ export const containerClass = style([ { listStyle: 'none', flexFlow: 'wrap', + marginBlockStart: '1px', }, ]); diff --git a/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.stories.tsx b/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.stories.tsx index b7d1f9976e..8a130cb6eb 100644 --- a/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.stories.tsx +++ b/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; +import { Badge } from '../Badge/Badge'; import type { IBreadcrumbsProps } from '../Breadcrumbs'; import { ProductIcon } from '../Icon'; import { Breadcrumbs } from './Breadcrumbs'; @@ -79,3 +80,36 @@ export const Primary: Story = { ); }, }; + +export const WithBadge: Story = { + name: 'Breadcrumbs With Badge', + args: { + icon: , + itemsCount: 3, + }, + render: ({ itemsCount, icon }) => { + const items = ItemArray.slice(0, itemsCount); + return ( + + Testnet + + } + > + {items.map((item, idx) => { + return ( + + {item} + + ); + })} + + ); + }, +}; diff --git a/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.tsx b/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.tsx index 04de594d50..3d7a5e0007 100644 --- a/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.tsx +++ b/packages/libs/kode-ui/src/components/Breadcrumbs/Breadcrumbs.tsx @@ -2,7 +2,7 @@ import type { FC, FunctionComponentElement } from 'react'; import React from 'react'; import type { AriaBreadcrumbsProps } from 'react-aria'; import { useBreadcrumbs } from 'react-aria'; -import { Box, Text } from '..'; +import { Stack, Text } from '..'; import { containerClass, navClass } from './Breadcrumbs.css'; import type { IBreadcrumbItemProps } from './BreadcrumbsItem'; @@ -11,10 +11,12 @@ export interface IBreadcrumbsProps extends AriaBreadcrumbsProps { | FunctionComponentElement | FunctionComponentElement[]; icon?: React.ReactElement; + badge?: React.ReactElement; } export const Breadcrumbs: FC = ({ icon, + badge, ...breadcrumbProps }) => { const { navProps } = useBreadcrumbs(breadcrumbProps); @@ -23,10 +25,11 @@ export const Breadcrumbs: FC = ({ return (