From 7352283d8fda45de3d22c383a6477714df0f6a98 Mon Sep 17 00:00:00 2001 From: Nik Graf Date: Mon, 3 Mar 2025 14:52:57 +0100 Subject: [PATCH 1/2] delegation experiment --- apps/events/src/components/delegate.tsx | 41 +++++++++++++++++++ .../events/src/lib/create-ethereum-account.ts | 11 +++++ apps/events/src/routeTree.gen.ts | 29 +++++++++++-- apps/events/src/routes/__root.tsx | 5 ++- apps/events/src/routes/settings/delegate.tsx | 14 +++++++ 5 files changed, 96 insertions(+), 4 deletions(-) create mode 100644 apps/events/src/components/delegate.tsx create mode 100644 apps/events/src/lib/create-ethereum-account.ts create mode 100644 apps/events/src/routes/settings/delegate.tsx diff --git a/apps/events/src/components/delegate.tsx b/apps/events/src/components/delegate.tsx new file mode 100644 index 00000000..948fb063 --- /dev/null +++ b/apps/events/src/components/delegate.tsx @@ -0,0 +1,41 @@ +import { Button } from '@/components/ui/button'; +import { createEthereumAccount } from '@/lib/create-ethereum-account'; +import { useDelegatedActions, usePrivy, useWallets } from '@privy-io/react-auth'; + +export const Delegate = () => { + const { user } = usePrivy(); + const { ready, wallets } = useWallets(); + const { delegateWallet, revokeWallets } = useDelegatedActions(); + + // find the embedded wallet to delegate from the array of the user's wallets + const walletToDelegate = wallets.find((wallet) => wallet.walletClientType === 'privy'); + + // // check if the wallet to delegate by inspecting the user's linked accounts + // const isAlreadyDelegated = !!user?.linkedAccounts.find( + // (account): account is WalletWithMetadata => account.type === 'wallet' && account.delegated, + // ); + + const onDelegate = async () => { + const { address, privateKey } = createEthereumAccount(); + if (!walletToDelegate || !ready) return; + await delegateWallet({ address: walletToDelegate.address, chainType: 'ethereum' }); + alert(`Delegated to ${address} with private key ${privateKey}`); + }; + + return ( + <> +

Delegate Access

+

Accounts

+ + + + ); +}; diff --git a/apps/events/src/lib/create-ethereum-account.ts b/apps/events/src/lib/create-ethereum-account.ts new file mode 100644 index 00000000..12c01ad6 --- /dev/null +++ b/apps/events/src/lib/create-ethereum-account.ts @@ -0,0 +1,11 @@ +import { bytesToHex, randomBytes } from '@noble/hashes/utils'; +import { privateKeyToAccount } from 'viem/accounts'; + +export const createEthereumAccount = () => { + const privateKey = `0x${bytesToHex(randomBytes(32))}` as `0x${string}`; + const account = privateKeyToAccount(privateKey); + return { + privateKey, + address: account.address, + }; +}; diff --git a/apps/events/src/routeTree.gen.ts b/apps/events/src/routeTree.gen.ts index db86e05e..61e2c975 100644 --- a/apps/events/src/routeTree.gen.ts +++ b/apps/events/src/routeTree.gen.ts @@ -15,6 +15,7 @@ import { createFileRoute } from '@tanstack/react-router' import { Route as rootRoute } from './routes/__root' import { Route as IndexImport } from './routes/index' import { Route as SpaceSpaceIdImport } from './routes/space/$spaceId' +import { Route as SettingsDelegateImport } from './routes/settings/delegate' // Create Virtual Routes @@ -40,6 +41,12 @@ const SpaceSpaceIdRoute = SpaceSpaceIdImport.update({ getParentRoute: () => rootRoute, } as any) +const SettingsDelegateRoute = SettingsDelegateImport.update({ + id: '/settings/delegate', + path: '/settings/delegate', + getParentRoute: () => rootRoute, +} as any) + // Populate the FileRoutesByPath interface declare module '@tanstack/react-router' { @@ -58,6 +65,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LoginLazyImport parentRoute: typeof rootRoute } + '/settings/delegate': { + id: '/settings/delegate' + path: '/settings/delegate' + fullPath: '/settings/delegate' + preLoaderRoute: typeof SettingsDelegateImport + parentRoute: typeof rootRoute + } '/space/$spaceId': { id: '/space/$spaceId' path: '/space/$spaceId' @@ -73,12 +87,14 @@ declare module '@tanstack/react-router' { export interface FileRoutesByFullPath { '/': typeof IndexRoute '/login': typeof LoginLazyRoute + '/settings/delegate': typeof SettingsDelegateRoute '/space/$spaceId': typeof SpaceSpaceIdRoute } export interface FileRoutesByTo { '/': typeof IndexRoute '/login': typeof LoginLazyRoute + '/settings/delegate': typeof SettingsDelegateRoute '/space/$spaceId': typeof SpaceSpaceIdRoute } @@ -86,27 +102,30 @@ export interface FileRoutesById { __root__: typeof rootRoute '/': typeof IndexRoute '/login': typeof LoginLazyRoute + '/settings/delegate': typeof SettingsDelegateRoute '/space/$spaceId': typeof SpaceSpaceIdRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/login' | '/space/$spaceId' + fullPaths: '/' | '/login' | '/settings/delegate' | '/space/$spaceId' fileRoutesByTo: FileRoutesByTo - to: '/' | '/login' | '/space/$spaceId' - id: '__root__' | '/' | '/login' | '/space/$spaceId' + to: '/' | '/login' | '/settings/delegate' | '/space/$spaceId' + id: '__root__' | '/' | '/login' | '/settings/delegate' | '/space/$spaceId' fileRoutesById: FileRoutesById } export interface RootRouteChildren { IndexRoute: typeof IndexRoute LoginLazyRoute: typeof LoginLazyRoute + SettingsDelegateRoute: typeof SettingsDelegateRoute SpaceSpaceIdRoute: typeof SpaceSpaceIdRoute } const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, LoginLazyRoute: LoginLazyRoute, + SettingsDelegateRoute: SettingsDelegateRoute, SpaceSpaceIdRoute: SpaceSpaceIdRoute, } @@ -122,6 +141,7 @@ export const routeTree = rootRoute "children": [ "/", "/login", + "/settings/delegate", "/space/$spaceId" ] }, @@ -131,6 +151,9 @@ export const routeTree = rootRoute "/login": { "filePath": "login.lazy.tsx" }, + "/settings/delegate": { + "filePath": "settings/delegate.tsx" + }, "/space/$spaceId": { "filePath": "space/$spaceId.tsx" } diff --git a/apps/events/src/routes/__root.tsx b/apps/events/src/routes/__root.tsx index 287ad96d..8f9b306a 100644 --- a/apps/events/src/routes/__root.tsx +++ b/apps/events/src/routes/__root.tsx @@ -30,7 +30,10 @@ export const Route = createRootRoute({