Skip to content

Commit 5fffa4f

Browse files
committed
Merge branch 'main' of github.com:graphprotocol/hypergraph into chris.whited/feat-354/move-app-template
2 parents 4798e01 + 141eb28 commit 5fffa4f

File tree

32 files changed

+539
-271
lines changed

32 files changed

+539
-271
lines changed

CONTRIBUTING.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,25 @@ cd apps/typesync
2323
pnpm publish --tag latest
2424
```
2525

26+
## Deploying your own SyncServer to Railway
27+
28+
Setup a service and attach a volume under `/data` to it.
29+
30+
Since cache-mounts on Railway need to prefixed with the service ID and BuildKit doesn’t expand variables there. You must give it a literal value for the mount ID.
31+
32+
To do so you can fill in the service ID below and run the command before your `railway up` command.
33+
More info here: https://docs.railway.com/guides/dockerfiles#cache-mounts
34+
Get the service ID by using CMD/CTRL+K and search for `Copy Service ID`.
35+
36+
```sh
37+
sed -i '' \
38+
's|\(--mount=type=cache,id=\)workspace|\1s/<service-id>-pnpm-store|' \
39+
Dockerfile
40+
railway up
41+
```
42+
43+
Note: By default horizontal scaling is disabled because of the attached volume.
44+
2645
## Deploying your own SyncServer to Fly.io (single instance)
2746

2847
```sh

Dockerfile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ WORKDIR /app
4949
COPY --from=build /workspace/deployment/out .
5050
# TODO: Remove this when we switch to an actual database.
5151
ENV DATABASE_URL="file:/data/production.sqlite"
52-
RUN npm run prisma migrate deploy --skip-generate
5352
EXPOSE 3030
5453
# can't use fly.io release_command because it doesn't mount the volume containing the sqlite db file
5554
CMD ["sh", "-c", "npm run prisma migrate deploy && node dist/index.js"]

apps/connect/src/routes/authenticate.tsx

Lines changed: 17 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import { createWalletClient, custom } from 'viem';
1616
import { privateKeyToAccount } from 'viem/accounts';
1717

1818
const CHAIN = import.meta.env.VITE_HYPERGRAPH_CHAIN === 'geogenesis' ? Connect.GEOGENESIS : Connect.GEO_TESTNET;
19+
const API_URL =
20+
import.meta.env.VITE_HYPERGRAPH_CHAIN === 'geogenesis'
21+
? `${Graph.MAINNET_API_ORIGIN}/graphql`
22+
: `${Graph.TESTNET_API_ORIGIN}/graphql`;
1923

2024
type AuthenticateSearch = {
2125
data: unknown;
@@ -135,19 +139,14 @@ function AuthenticateComponent() {
135139
const accountAddress = useSelector(StoreConnect.store, (state) => state.context.accountAddress);
136140
const keys = useSelector(StoreConnect.store, (state) => state.context.keys);
137141

138-
const { signMessage } = usePrivy();
139142
const { wallets } = useWallets();
140143
const embeddedWallet = wallets.find((wallet) => wallet.walletClientType === 'privy') || wallets[0];
141144

142145
const state = useSelector(componentStore, (state) => state.context);
143146
const [selectedPrivateSpaces, setSelectedPrivateSpaces] = useState<Set<string>>(new Set());
144147

145148
const { isPending: privateSpacesPending, error: privateSpacesError, data: privateSpacesData } = usePrivateSpaces();
146-
const {
147-
isPending: publicSpacesPending,
148-
error: publicSpacesError,
149-
data: publicSpacesData,
150-
} = usePublicSpaces(`${Graph.TESTNET_API_ORIGIN}/graphql`);
149+
const { data: publicSpacesData } = usePublicSpaces(API_URL);
151150

152151
useEffect(() => {
153152
const run = async () => {
@@ -261,7 +260,7 @@ function AuthenticateComponent() {
261260
id: keyData.id,
262261
ciphertext: Utils.bytesToHex(keyBox.keyBoxCiphertext),
263262
nonce: Utils.bytesToHex(keyBox.keyBoxNonce),
264-
authorPublicKey: appIdentity.encryptionPublicKey,
263+
authorPublicKey: keys.encryptionPublicKey,
265264
accountAddress: accountAddress,
266265
};
267266
});
@@ -334,21 +333,6 @@ function AuthenticateComponent() {
334333
transport: custom(privyProvider),
335334
});
336335

337-
const signer: Identity.Signer = {
338-
getAddress: async () => {
339-
const [address] = await walletClient.getAddresses();
340-
return address;
341-
},
342-
signMessage: async (message: string) => {
343-
if (embeddedWallet.walletClientType === 'privy') {
344-
const { signature } = await signMessage({ message });
345-
return signature;
346-
}
347-
const [address] = await walletClient.getAddresses();
348-
return await walletClient.signMessage({ account: address, message });
349-
},
350-
};
351-
352336
const newAppIdentity = Connect.createAppIdentity();
353337

354338
console.log('creating smart session');
@@ -389,28 +373,21 @@ function AuthenticateComponent() {
389373
});
390374

391375
console.log('encrypting app identity');
392-
const { ciphertext, nonce } = await Connect.encryptAppIdentity(
393-
signer,
394-
newAppIdentity.address,
395-
newAppIdentity.addressPrivateKey,
396-
permissionId,
397-
keys,
398-
);
376+
const { ciphertext } = await Connect.encryptAppIdentity({ ...newAppIdentity, permissionId }, keys);
399377
console.log('proving ownership');
400378
const { accountProof, keyProof } = await Identity.proveIdentityOwnership(
401379
smartAccountClient,
402380
accountAddress,
403-
keys,
381+
newAppIdentity,
404382
);
405383

406384
const message: Messages.RequestConnectCreateAppIdentity = {
407385
appId: state.appInfo.appId,
408386
address: newAppIdentity.address,
409387
accountAddress,
410-
signaturePublicKey: newAppIdentity.signaturePublicKey,
411-
encryptionPublicKey: newAppIdentity.encryptionPublicKey,
388+
signaturePublicKey: keys.signaturePublicKey,
389+
encryptionPublicKey: keys.encryptionPublicKey,
412390
ciphertext,
413-
nonce,
414391
accountProof,
415392
keyProof,
416393
};
@@ -424,14 +401,16 @@ function AuthenticateComponent() {
424401
body: JSON.stringify(message),
425402
});
426403
const appIdentityResponse = await response.json();
404+
// TODO: All apps are essentially using the same keys, we should change to using
405+
// the newly created app identity keys, but that requires changing a lot of the verification logic in the server and HypergraphAppContext
427406
await encryptSpacesAndRedirect({
428407
accountAddress,
429408
appIdentity: {
430409
address: newAppIdentity.address,
431410
addressPrivateKey: newAppIdentity.addressPrivateKey,
432411
accountAddress,
433-
encryptionPrivateKey: keys.encryptionPrivateKey,
434-
signaturePrivateKey: keys.signaturePrivateKey,
412+
encryptionPrivateKey: newAppIdentity.encryptionPrivateKey,
413+
signaturePrivateKey: newAppIdentity.signaturePrivateKey,
435414
encryptionPublicKey: newAppIdentity.encryptionPublicKey,
436415
signaturePublicKey: newAppIdentity.signaturePublicKey,
437416
sessionToken: appIdentityResponse.appIdentity.sessionToken,
@@ -451,48 +430,16 @@ function AuthenticateComponent() {
451430
};
452431

453432
const decryptAppIdentityAndRedirect = async () => {
454-
if (!state.appIdentityResponse) {
433+
if (!state.appIdentityResponse || !keys) {
455434
return;
456435
}
457436

458-
const privyProvider = await embeddedWallet.getEthereumProvider();
459-
const walletClient = createWalletClient({
460-
account: embeddedWallet.address as `0x${string}`,
461-
chain: CHAIN,
462-
transport: custom(privyProvider),
463-
});
464-
465-
const signer: Identity.Signer = {
466-
getAddress: async () => {
467-
const [address] = await walletClient.getAddresses();
468-
return address;
469-
},
470-
signMessage: async (message: string) => {
471-
if (embeddedWallet.walletClientType === 'privy') {
472-
const { signature } = await signMessage({ message });
473-
return signature;
474-
}
475-
const [address] = await walletClient.getAddresses();
476-
return await walletClient.signMessage({ account: address, message });
477-
},
478-
};
479-
480-
const decryptedIdentity = await Connect.decryptAppIdentity(
481-
signer,
482-
state.appIdentityResponse.ciphertext,
483-
state.appIdentityResponse.nonce,
484-
);
437+
const decryptedIdentity = await Connect.decryptAppIdentity(state.appIdentityResponse.ciphertext, keys);
485438
await encryptSpacesAndRedirect({
486439
accountAddress: state.appIdentityResponse.accountAddress,
487440
appIdentity: {
488-
address: decryptedIdentity.address,
489-
addressPrivateKey: decryptedIdentity.addressPrivateKey,
441+
...decryptedIdentity,
490442
accountAddress: state.appIdentityResponse.accountAddress,
491-
permissionId: decryptedIdentity.permissionId,
492-
encryptionPrivateKey: decryptedIdentity.encryptionPrivateKey,
493-
signaturePrivateKey: decryptedIdentity.signaturePrivateKey,
494-
encryptionPublicKey: decryptedIdentity.encryptionPublicKey,
495-
signaturePublicKey: decryptedIdentity.signaturePublicKey,
496443
sessionToken: state.appIdentityResponse.sessionToken,
497444
sessionTokenExpires: new Date(state.appIdentityResponse.sessionTokenExpires),
498445
},

apps/events/src/Boot.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,11 @@ declare module '@tanstack/react-router' {
1515

1616
export function Boot() {
1717
return (
18-
<HypergraphAppProvider syncServerUri="http://localhost:3030" mapping={mapping}>
18+
<HypergraphAppProvider
19+
syncServerUri="http://localhost:3030"
20+
mapping={mapping}
21+
appId="93bb8907-085a-4a0e-83dd-62b0dc98e793"
22+
>
1923
<RouterProvider router={router} />
2024
</HypergraphAppProvider>
2125
);

apps/events/src/routes/login.lazy.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ function Login() {
1616
storage: localStorage,
1717
connectUrl: 'http://localhost:5180',
1818
successUrl: `${window.location.origin}/authenticate-success`,
19-
appId: '93bb8907-085a-4a0e-83dd-62b0dc98e793',
2019
redirectFn: (url: URL) => {
2120
window.location.href = url.toString();
2221
},

apps/next-example/src/components/providers.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@ export default function Providers({ children }: { children: React.ReactNode }) {
77
const storage = typeof window !== 'undefined' ? window.localStorage : (undefined as unknown as Storage);
88

99
return (
10-
<HypergraphAppProvider syncServerUri="http://localhost:3030" mapping={{}}>
10+
<HypergraphAppProvider
11+
syncServerUri="http://localhost:3030"
12+
mapping={{}}
13+
appId="83aa8907-085b-430f-1296-ab87dc98e793"
14+
>
1115
{children}
1216
</HypergraphAppProvider>
1317
);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
Warnings:
3+
4+
- You are about to drop the column `nonce` on the `AppIdentity` table. All the data in the column will be lost.
5+
6+
*/
7+
-- RedefineTables
8+
PRAGMA defer_foreign_keys=ON;
9+
PRAGMA foreign_keys=OFF;
10+
CREATE TABLE "new_AppIdentity" (
11+
"address" TEXT NOT NULL PRIMARY KEY,
12+
"ciphertext" TEXT NOT NULL,
13+
"signaturePublicKey" TEXT NOT NULL,
14+
"encryptionPublicKey" TEXT NOT NULL,
15+
"accountProof" TEXT NOT NULL,
16+
"keyProof" TEXT NOT NULL,
17+
"accountAddress" TEXT NOT NULL,
18+
"appId" TEXT NOT NULL,
19+
"sessionToken" TEXT NOT NULL,
20+
"sessionTokenExpires" DATETIME NOT NULL,
21+
CONSTRAINT "AppIdentity_accountAddress_fkey" FOREIGN KEY ("accountAddress") REFERENCES "Account" ("address") ON DELETE RESTRICT ON UPDATE CASCADE
22+
);
23+
INSERT INTO "new_AppIdentity" ("accountAddress", "accountProof", "address", "appId", "ciphertext", "encryptionPublicKey", "keyProof", "sessionToken", "sessionTokenExpires", "signaturePublicKey") SELECT "accountAddress", "accountProof", "address", "appId", "ciphertext", "encryptionPublicKey", "keyProof", "sessionToken", "sessionTokenExpires", "signaturePublicKey" FROM "AppIdentity";
24+
DROP TABLE "AppIdentity";
25+
ALTER TABLE "new_AppIdentity" RENAME TO "AppIdentity";
26+
CREATE INDEX "AppIdentity_sessionToken_idx" ON "AppIdentity"("sessionToken");
27+
CREATE UNIQUE INDEX "AppIdentity_accountAddress_appId_key" ON "AppIdentity"("accountAddress", "appId");
28+
PRAGMA foreign_keys=ON;
29+
PRAGMA defer_foreign_keys=OFF;

apps/server/prisma/schema.prisma

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ model Account {
115115
model AppIdentity {
116116
address String @id
117117
ciphertext String
118-
nonce String
119118
signaturePublicKey String
120119
encryptionPublicKey String
121120
accountProof String
@@ -129,7 +128,6 @@ model AppIdentity {
129128
sessionTokenExpires DateTime
130129
131130
@@unique([accountAddress, appId])
132-
@@unique([accountAddress, nonce])
133131
@@index([sessionToken])
134132
}
135133

apps/server/src/handlers/applySpaceEvent.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { Messages } from '@graphprotocol/hypergraph';
44
import { Identity, SpaceEvents } from '@graphprotocol/hypergraph';
55

66
import { prisma } from '../prisma.js';
7-
import { getConnectIdentity } from './getConnectIdentity.js';
7+
import { getAppOrConnectIdentity } from './getAppOrConnectIdentity.js';
88

99
type Params = {
1010
accountAddress: string;
@@ -40,7 +40,7 @@ export async function applySpaceEvent({ accountAddress, spaceId, event, keyBoxes
4040
orderBy: { counter: 'desc' },
4141
});
4242

43-
const getVerifiedIdentity = (accountAddressToFetch: string) => {
43+
const getVerifiedIdentity = (accountAddressToFetch: string, publicKey: string) => {
4444
console.log('getVerifiedIdentity', accountAddressToFetch, accountAddress);
4545
// applySpaceEvent is only allowed to be called by the account that is applying the event
4646
if (accountAddressToFetch !== accountAddress) {
@@ -49,7 +49,8 @@ export async function applySpaceEvent({ accountAddress, spaceId, event, keyBoxes
4949

5050
return Effect.gen(function* () {
5151
const identity = yield* Effect.tryPromise({
52-
try: () => getConnectIdentity({ accountAddress: accountAddressToFetch }),
52+
try: () =>
53+
getAppOrConnectIdentity({ accountAddress: accountAddressToFetch, signaturePublicKey: publicKey, spaceId }),
5354
catch: () => new Identity.InvalidIdentityError(),
5455
});
5556
return identity;

apps/server/src/handlers/create-app-identity.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ export const createAppIdentity = async ({
1919
address,
2020
appId,
2121
ciphertext,
22-
nonce,
2322
signaturePublicKey,
2423
encryptionPublicKey,
2524
accountProof,
@@ -43,7 +42,6 @@ export const createAppIdentity = async ({
4342
accountAddress,
4443
appId,
4544
ciphertext,
46-
nonce,
4745
signaturePublicKey,
4846
encryptionPublicKey,
4947
accountProof,

0 commit comments

Comments
 (0)