Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion apps/connect/src/routes/authenticate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -282,10 +282,11 @@ function AuthenticateComponent() {
nonce: appInfo.appNonce,
ephemeralPublicKey: appInfo.ephemeralEncryptionPublicKey,
appIdentityAddress: appIdentity.address,
appIdentityAddressPrivateKey: appIdentity.addressPrivateKey,
accountAddress: accountAddress,
encryptionPrivateKey: appIdentity.encryptionPrivateKey,
signaturePrivateKey: appIdentity.signaturePrivateKey,
signaturePublicKey: appIdentity.signaturePublicKey,
appIdentityAddressPrivateKey: appIdentity.addressPrivateKey,
encryptionPublicKey: appIdentity.encryptionPublicKey,
spaces: spacesData?.map((space) => ({ id: space.id })) ?? [],
expiry: appInfo.expiry,
Expand Down Expand Up @@ -364,6 +365,7 @@ function AuthenticateComponent() {
appIdentity: {
address: newAppIdentity.address,
addressPrivateKey: newAppIdentity.addressPrivateKey,
accountAddress,
encryptionPrivateKey: keys.encryptionPrivateKey,
signaturePrivateKey: keys.signaturePrivateKey,
encryptionPublicKey: newAppIdentity.encryptionPublicKey,
Expand Down Expand Up @@ -420,6 +422,7 @@ function AuthenticateComponent() {
appIdentity: {
address: decryptedIdentity.address,
addressPrivateKey: decryptedIdentity.addressPrivateKey,
accountAddress: decryptedIdentity.accountAddress,
encryptionPrivateKey: decryptedIdentity.encryptionPrivateKey,
signaturePrivateKey: decryptedIdentity.signaturePrivateKey,
encryptionPublicKey: decryptedIdentity.encryptionPublicKey,
Expand Down
1 change: 1 addition & 0 deletions apps/events/src/routes/authenticate-success.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ function RouteComponent() {
setIdentity({
address: parsedAuthParams.appIdentityAddress,
addressPrivateKey: parsedAuthParams.appIdentityAddressPrivateKey,
accountAddress: parsedAuthParams.accountAddress,
signaturePublicKey: parsedAuthParams.signaturePublicKey,
signaturePrivateKey: parsedAuthParams.signaturePrivateKey,
encryptionPublicKey: parsedAuthParams.encryptionPublicKey,
Expand Down
20 changes: 19 additions & 1 deletion apps/events/src/routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';
import { store } from '@graphprotocol/hypergraph';
import { useHypergraphApp } from '@graphprotocol/hypergraph-react';
import { useHypergraphApp, useSpaces } from '@graphprotocol/hypergraph-react';
import { Link, createFileRoute } from '@tanstack/react-router';
import { useSelector } from '@xstate/store/react';
import { useEffect, useState } from 'react';
Expand All @@ -12,6 +12,7 @@ export const Route = createFileRoute('/')({
});

function Index() {
const { data: publicSpaces } = useSpaces({ mode: 'public' });
const spaces = useSelector(store, (state) => state.context.spaces);
const [spaceName, setSpaceName] = useState('');

Expand Down Expand Up @@ -89,6 +90,8 @@ function Index() {
Create space
</Button>
</div>

<h2 className="text-lg font-bold">Private Spaces</h2>
<ul className="flex flex-col gap-2">
{spaces.length === 0 && <div>No spaces</div>}
{spaces.map((space) => {
Expand All @@ -106,6 +109,21 @@ function Index() {
})}
</ul>

<h2 className="text-lg font-bold">Public Spaces</h2>
<ul className="flex flex-col gap-2">
{publicSpaces?.map((space) => {
return (
<li key={space.id}>
<Card>
<CardHeader>
<CardTitle>{space.name}</CardTitle>
</CardHeader>
</Card>
</li>
);
})}
</ul>

<div className="flex flex-col gap-2">
<h2 className="text-lg font-bold">Account Inboxes</h2>
<Button
Expand Down
7 changes: 6 additions & 1 deletion packages/hypergraph-react/src/HypergraphAppContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
Utils,
store,
} from '@graphprotocol/hypergraph';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { useSelector as useSelectorStore } from '@xstate/store/react';
import { Effect, Exit } from 'effect';
import * as Schema from 'effect/Schema';
Expand All @@ -38,6 +39,8 @@ import type { Address } from 'viem';

const decodeResponseMessage = Schema.decodeUnknownEither(Messages.ResponseMessage);

const queryClient = new QueryClient();

export type HypergraphAppCtx = {
// auth related
logout(): void;
Expand Down Expand Up @@ -1352,7 +1355,9 @@ export function HypergraphAppProvider({
ensureSpaceInbox: ensureSpaceInboxForContext,
}}
>
<RepoContext.Provider value={repo}>{children}</RepoContext.Provider>
<QueryClientProvider client={queryClient}>
<RepoContext.Provider value={repo}>{children}</RepoContext.Provider>
</QueryClientProvider>
</HypergraphAppContext.Provider>
);
}
9 changes: 1 addition & 8 deletions packages/hypergraph-react/src/HypergraphSpaceContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import type { AnyDocumentId, DocHandle, Repo } from '@automerge/automerge-repo';
import { useRepo } from '@automerge/automerge-repo-react-hooks';
import { Entity, Utils } from '@graphprotocol/hypergraph';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import * as Schema from 'effect/Schema';
import { type ReactNode, createContext, useContext, useMemo, useRef, useState, useSyncExternalStore } from 'react';

Expand All @@ -25,8 +24,6 @@ function useHypergraphSpaceInternal() {
return context as HypergraphContext;
}

const queryClient = new QueryClient();

export function HypergraphSpaceProvider({ space, children }: { space: string; children: ReactNode }) {
const repo = useRepo();
const ref = useRef<HypergraphContext | undefined>(undefined);
Expand All @@ -44,11 +41,7 @@ export function HypergraphSpaceProvider({ space, children }: { space: string; ch
};
}

return (
<QueryClientProvider client={queryClient}>
<HypergraphReactContext.Provider value={current}>{children}</HypergraphReactContext.Provider>
</QueryClientProvider>
);
return <HypergraphReactContext.Provider value={current}>{children}</HypergraphReactContext.Provider>;
}

export function useCreateEntity<const S extends Entity.AnyNoContext>(type: S) {
Expand Down
48 changes: 48 additions & 0 deletions packages/hypergraph-react/src/hooks/use-spaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { store } from '@graphprotocol/hypergraph/store';
import { useQuery } from '@tanstack/react-query';
import { useSelector } from '@xstate/store/react';
import { gql, request } from 'graphql-request';
import { GEO_API_TESTNET_ENDPOINT } from '../internal/constants.js';

const publicSpacesQueryDocument = gql`
query Spaces($accountAddress: String!) {
spaces(filter: {
member: { is: $accountAddress }
}) {
id
spaceAddress
entity {
name
}
}
}
`;

type PublicSpacesQueryResult = {
spaces: {
id: string;
spaceAddress: string;
entity: {
name: string;
};
}[];
};

export const useSpaces = (params: { mode: 'public' }) => {
const accountAddress = useSelector(store, (state) => state.context.identity?.accountAddress);
return useQuery({
queryKey: ['hypergraph-spaces', params.mode],
queryFn: async () => {
const result = await request<PublicSpacesQueryResult>(GEO_API_TESTNET_ENDPOINT, publicSpacesQueryDocument, {
accountAddress,
});
return result?.spaces
? result.spaces.map((space) => ({
id: space.id,
name: space.entity.name,
spaceAddress: space.spaceAddress,
}))
: [];
},
});
};
1 change: 1 addition & 0 deletions packages/hypergraph-react/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export { PublishDiff } from './components/publish-diff/publish-diff.js';
export { createWalletClient } from './create-wallet-client.js';
export { useSpaces } from './hooks/use-spaces.js';
export { useExternalAccountInbox } from './hooks/useExternalAccountInbox.js';
export { useExternalSpaceInbox } from './hooks/useExternalSpaceInbox.js';
export { useOwnAccountInbox } from './hooks/useOwnAccountInbox.js';
Expand Down
1 change: 1 addition & 0 deletions packages/hypergraph/src/connect/create-callback-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type CreateAuthUrlParams = {
appId: string;
appIdentityAddress: string;
appIdentityAddressPrivateKey: string;
accountAddress: string;
signaturePublicKey: string;
signaturePrivateKey: string;
encryptionPublicKey: string;
Expand Down
1 change: 1 addition & 0 deletions packages/hypergraph/src/connect/identity-encryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,5 +228,6 @@ export const decryptAppIdentity = async (
signaturePrivateKey,
address: appIdentityAddress,
addressPrivateKey: appIdentityAddressPrivateKey,
accountAddress,
};
};
1 change: 1 addition & 0 deletions packages/hypergraph/src/connect/parse-callback-params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export const parseCallbackParams = ({
return Effect.succeed({
appIdentityAddress: data.appIdentityAddress,
appIdentityAddressPrivateKey: data.appIdentityAddressPrivateKey,
accountAddress: data.accountAddress,
signaturePublicKey: data.signaturePublicKey,
signaturePrivateKey: data.signaturePrivateKey,
encryptionPublicKey: data.encryptionPublicKey,
Expand Down
1 change: 1 addition & 0 deletions packages/hypergraph/src/connect/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export type PrivateAppIdentity = IdentityKeys & {
addressPrivateKey: string;
sessionToken: string;
sessionTokenExpires: Date;
accountAddress: string;
};

export class InvalidIdentityError {
Expand Down
5 changes: 5 additions & 0 deletions packages/hypergraph/src/identity/auth-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { Storage } from './types.js';
export const storeIdentity = (storage: Storage, identity: PrivateAppIdentity) => {
storage.setItem('hypergraph:app-identity-address', identity.address);
storage.setItem('hypergraph:app-identity-address-private-key', identity.addressPrivateKey);
storage.setItem('hypergraph:app-identity-account-address', identity.accountAddress);
storage.setItem('hypergraph:signature-public-key', identity.signaturePublicKey);
storage.setItem('hypergraph:signature-private-key', identity.signaturePrivateKey);
storage.setItem('hypergraph:encryption-public-key', identity.encryptionPublicKey);
Expand All @@ -15,6 +16,7 @@ export const storeIdentity = (storage: Storage, identity: PrivateAppIdentity) =>
export const loadIdentity = (storage: Storage): PrivateAppIdentity | null => {
const address = storage.getItem('hypergraph:app-identity-address');
const addressPrivateKey = storage.getItem('hypergraph:app-identity-address-private-key');
const accountAddress = storage.getItem('hypergraph:app-identity-account-address');
const signaturePublicKey = storage.getItem('hypergraph:signature-public-key');
const signaturePrivateKey = storage.getItem('hypergraph:signature-private-key');
const encryptionPublicKey = storage.getItem('hypergraph:encryption-public-key');
Expand All @@ -24,6 +26,7 @@ export const loadIdentity = (storage: Storage): PrivateAppIdentity | null => {
if (
!address ||
!addressPrivateKey ||
!accountAddress ||
!signaturePublicKey ||
!signaturePrivateKey ||
!encryptionPublicKey ||
Expand All @@ -36,6 +39,7 @@ export const loadIdentity = (storage: Storage): PrivateAppIdentity | null => {
return {
address,
addressPrivateKey,
accountAddress,
signaturePublicKey,
signaturePrivateKey,
encryptionPublicKey,
Expand All @@ -48,6 +52,7 @@ export const loadIdentity = (storage: Storage): PrivateAppIdentity | null => {
export const wipeIdentity = (storage: Storage) => {
storage.removeItem('hypergraph:app-identity-address');
storage.removeItem('hypergraph:app-identity-address-private-key');
storage.removeItem('hypergraph:app-identity-account-address');
storage.removeItem('hypergraph:signature-public-key');
storage.removeItem('hypergraph:signature-private-key');
storage.removeItem('hypergraph:encryption-public-key');
Expand Down
3 changes: 2 additions & 1 deletion packages/hypergraph/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,7 +489,8 @@ export const store: Store<StoreContext, StoreEvent, GenericEventObject> = create
return {
...context,
authenticated: true,
identity: event.identity,
// TODO: remove hard-coded account address and use the one from the identity
identity: { ...event.identity, accountAddress: '0xBE0298aF8D440bEFA78E7e8A538D8ecBFF06bfC7' },
};
},
resetAuth: (context) => {
Expand Down
1 change: 1 addition & 0 deletions packages/hypergraph/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export type ConnectAuthPayload = Schema.Schema.Type<typeof ConnectAuthPayload>;
export const ConnectCallbackResult = Schema.Struct({
appIdentityAddress: Schema.String,
appIdentityAddressPrivateKey: Schema.String,
accountAddress: Schema.String,
signaturePublicKey: Schema.String,
signaturePrivateKey: Schema.String,
encryptionPublicKey: Schema.String,
Expand Down
Loading