Skip to content

Commit 3f91e84

Browse files
authored
hook for publishing public data (#416)
1 parent ddae2c0 commit 3f91e84

File tree

8 files changed

+71
-49
lines changed

8 files changed

+71
-49
lines changed

.changeset/tame-eagles-crash.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"create-hypergraph": patch
3+
---
4+
5+
Update vite template to use usePublishToPublicSpace
6+

.changeset/tidy-ghosts-clean.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@graphprotocol/hypergraph-react": patch
3+
---
4+
5+
Add usePublishToPublicSpace hook
6+

.tool-versions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pnpm 10.14.0

apps/create-hypergraph/template-vite-react/src/routes/private-space/$space-id.tsx

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,11 @@ import { Button } from '@/components/ui/button';
22
import { Address } from '@/schema';
33
import {
44
HypergraphSpaceProvider,
5-
preparePublish,
6-
publishOps,
75
useCreateEntity,
8-
useHypergraphApp,
96
useQuery,
107
useSpace,
118
useSpaces,
9+
usePublishToPublicSpace
1210
} from '@graphprotocol/hypergraph-react';
1311
import { createFileRoute } from '@tanstack/react-router';
1412
import { useState } from 'react';
@@ -34,7 +32,10 @@ function PrivateSpace() {
3432
const [selectedSpace, setSelectedSpace] = useState<string>('');
3533
const createAddress = useCreateEntity(Address);
3634
const [addressName, setAddressName] = useState('');
37-
const { getSmartSessionClient } = useHypergraphApp();
35+
const { mutate: publishToPublicSpace, isPending } = usePublishToPublicSpace({
36+
onSuccess: () => alert('Address published to public space'),
37+
onError: () => alert('Error publishing address to public space')
38+
});
3839

3940
if (!ready) {
4041
return (
@@ -53,31 +54,6 @@ function PrivateSpace() {
5354
setAddressName('');
5455
};
5556

56-
const publishToPublicSpace = async (address: Address) => {
57-
if (!selectedSpace) {
58-
alert('No space selected');
59-
return;
60-
}
61-
try {
62-
const { ops } = await preparePublish({ entity: address, publicSpace: selectedSpace });
63-
const smartSessionClient = await getSmartSessionClient();
64-
if (!smartSessionClient) {
65-
throw new Error('Missing smartSessionClient');
66-
}
67-
const publishResult = await publishOps({
68-
ops,
69-
space: selectedSpace,
70-
name: 'Publish Address',
71-
walletClient: smartSessionClient,
72-
});
73-
console.log(publishResult, ops);
74-
alert('Address published to public space');
75-
} catch (error) {
76-
console.error(error);
77-
alert('Error publishing address to public space');
78-
}
79-
};
80-
8157
return (
8258
<div className="min-h-screen bg-background">
8359
<div className="container mx-auto px-4 py-8 max-w-4xl">
@@ -153,8 +129,8 @@ function PrivateSpace() {
153129
</div>
154130

155131
<Button
156-
onClick={() => publishToPublicSpace(address)}
157-
disabled={!selectedSpace}
132+
onClick={() => publishToPublicSpace({ entity: address, spaceId: selectedSpace })}
133+
disabled={!selectedSpace || isPending}
158134
variant="outline"
159135
size="sm"
160136
className="w-full"

docs/docs/publishing-public-data.md

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,35 +39,24 @@ const { result } = publishOps({
3939
});
4040
```
4141

42-
Here is a full example flow:
42+
Additionally, we export a `usePublishToPublishSpace` hook which abstracts the above functionality into a single function call. This function internally uses React Query's useMutate hook, so you have access to the same state machine and callback functions.
4343

4444
```tsx
45-
import { publishOps, useHypergraphApp } from "@graphprotocol/hypergraph-react";
45+
import { usePublishToPublicSpace, useHypergraphApp } from "@graphprotocol/hypergraph-react";
4646

4747
const MyComponent = ({ publicSpaceId }: { publicSpaceId: string }) => {
4848
const { getSmartSessionClient } = useHypergraphApp();
4949
const { data: events } = useQuery(Event, { mode: "private" });
50+
const { mutate, isPending } = usePublishToPublicSpace();
5051

51-
const publishEvent = async (entity) => {
52-
const smartSessionClient = await getSmartSessionClient();
53-
54-
const { ops } = preparePublish({
55-
entity: entity,
56-
publicSpace: publicSpaceId,
57-
});
58-
59-
const result = await publishOps({
60-
ops,
61-
walletClient: smartSessionClient,
62-
space: publicSpaceId,
63-
name: "Create Event",
64-
});
65-
};
52+
if (isPending) {
53+
return <div>Publishing...</div>
54+
}
6655

6756
return (
6857
<div>
6958
{events.map((event) => (
70-
<button key={event.id} onClick={() => publishEvent(event)}>
59+
<button key={event.id} onClick={() => mutate({ entity: event, spaceId: publicSpaceId })}>
7160
{event.name}
7261
</button>
7362
))}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { Entity } from '@graphprotocol/hypergraph';
2+
import { type UseMutationOptions, useMutation } from '@tanstack/react-query';
3+
import { useHypergraphApp } from '../HypergraphAppContext.js';
4+
import { preparePublish } from '../prepare-publish.js';
5+
import { publishOps } from '../publish-ops.js';
6+
import type { OmitStrict } from '../types.js';
7+
8+
type Variables<S extends Entity.AnyNoContext> = {
9+
entity: S;
10+
spaceId: string;
11+
};
12+
13+
type UsePublishToSpaceOptions = OmitStrict<
14+
UseMutationOptions<Awaited<ReturnType<typeof publishOps>>, Error, Variables<Entity.AnyNoContext>, unknown>,
15+
'mutationFn' | 'mutationKey'
16+
>;
17+
18+
export function usePublishToPublicSpace(options: UsePublishToSpaceOptions = {}) {
19+
const { getSmartSessionClient } = useHypergraphApp();
20+
21+
return useMutation({
22+
...options,
23+
mutationFn: async ({ entity, spaceId }) => {
24+
const { ops } = await preparePublish({
25+
entity,
26+
publicSpace: spaceId,
27+
});
28+
const smartSessionClient = await getSmartSessionClient();
29+
if (!smartSessionClient) {
30+
throw new Error('Missing smartSessionClient');
31+
}
32+
33+
return await publishOps({
34+
ops,
35+
space: spaceId,
36+
name: 'Published entity',
37+
walletClient: smartSessionClient,
38+
});
39+
},
40+
});
41+
}

packages/hypergraph-react/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export { useExternalSpaceInbox } from './hooks/useExternalSpaceInbox.js';
2222
export { useOwnAccountInbox } from './hooks/useOwnAccountInbox.js';
2323
export { useOwnSpaceInbox } from './hooks/useOwnSpaceInbox.js';
2424
export { usePublicAccountInboxes } from './hooks/usePublicAccountInboxes.js';
25+
export { usePublishToPublicSpace } from './hooks/usePublishToSpace.js';
2526
export { generateDeleteOps as _generateDeleteOps } from './internal/generate-delete-ops.js';
2627
export { useCreateEntityPublic as _useCreateEntityPublic } from './internal/use-create-entity-public.js';
2728
export { useDeleteEntityPublic as _useDeleteEntityPublic } from './internal/use-delete-entity-public.js';

packages/hypergraph-react/src/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import type { Op } from '@graphprotocol/grc-20';
22
import type { Entity } from '@graphprotocol/hypergraph';
33
import type * as Schema from 'effect/Schema';
44

5+
export type OmitStrict<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
6+
57
export type EntityLike = {
68
id: string;
79
[key: string]: unknown;

0 commit comments

Comments
 (0)