Skip to content

Commit fdeb7c6

Browse files
committed
wip on integrating with connect
1 parent 3fee157 commit fdeb7c6

File tree

10 files changed

+176
-83
lines changed

10 files changed

+176
-83
lines changed

apps/connect/src/routes/authenticate.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ function AuthenticateComponent() {
154154
{
155155
headers: {
156156
'privy-id-token': identityToken,
157+
'account-address': accountAddress,
157158
'Content-Type': 'application/json',
158159
},
159160
},
@@ -274,6 +275,7 @@ function AuthenticateComponent() {
274275
{
275276
headers: {
276277
'privy-id-token': identityToken,
278+
'account-address': accountAddress,
277279
'Content-Type': 'application/json',
278280
},
279281
method: 'POST',
@@ -357,6 +359,7 @@ function AuthenticateComponent() {
357359
const response = await fetch(`${import.meta.env.VITE_HYPERGRAPH_SYNC_SERVER_ORIGIN}/connect/app-identity`, {
358360
headers: {
359361
'privy-id-token': identityToken,
362+
'account-address': accountAddress,
360363
'Content-Type': 'application/json',
361364
},
362365
method: 'POST',

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

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import { Button } from '@/components/ui/button';
2-
import { Connect, type Identity } from '@graphprotocol/hypergraph';
3-
import { useIdentityToken, usePrivy, useWallets } from '@privy-io/react-auth';
2+
import { Connect, type Identity, StoreConnect } from '@graphprotocol/hypergraph';
3+
import { GEOGENESIS, GEO_TESTNET } from '@graphprotocol/hypergraph/connect/smart-account';
4+
import { type ConnectedWallet, useIdentityToken, usePrivy, useWallets } from '@privy-io/react-auth';
45
import { createLazyFileRoute, useRouter } from '@tanstack/react-router';
6+
import { useSelector } from 'node_modules/@xstate/store/dist/declarations/src/react';
57
import { useCallback, useEffect, useState } from 'react';
6-
import { createWalletClient, custom, getAddress } from 'viem';
8+
import { type WalletClient, createWalletClient, custom } from 'viem';
79
import { mainnet } from 'viem/chains';
810

911
const syncServerUri = import.meta.env.VITE_HYPERGRAPH_SYNC_SERVER_ORIGIN;
@@ -21,18 +23,35 @@ function Login() {
2123
const { identityToken } = useIdentityToken();
2224

2325
const hypergraphLogin = useCallback(
24-
async (signer: Identity.Signer) => {
25-
if (!signer || !identityToken) {
26+
async (walletClient: WalletClient, embeddedWallet: ConnectedWallet) => {
27+
if (!identityToken) {
2628
return;
2729
}
30+
const signer: Identity.Signer = {
31+
getAddress: async () => {
32+
const [address] = await walletClient.getAddresses();
33+
return address;
34+
},
35+
signMessage: async (message: string) => {
36+
if (embeddedWallet.walletClientType === 'privy') {
37+
const { signature } = await signMessage({ message });
38+
return signature;
39+
}
40+
const [address] = await walletClient.getAddresses();
41+
return await walletClient.signMessage({ account: address, message });
42+
},
43+
};
44+
2845
const address = await signer.getAddress();
2946
if (!address) {
3047
return;
3148
}
32-
const accountAddress = getAddress(address);
33-
await Connect.login(signer, accountAddress, syncServerUri, storage, identityToken);
49+
const chain = import.meta.env.VITE_HYPERGRAPH_CHAIN === 'geogenesis' ? GEOGENESIS : GEO_TESTNET;
50+
const rpcUrl = import.meta.env.VITE_HYPERGRAPH_RPC_URL;
51+
52+
await Connect.login({ walletClient, signer, syncServerUri, storage, identityToken, rpcUrl, chain });
3453
},
35-
[identityToken],
54+
[identityToken, signMessage],
3655
);
3756

3857
useEffect(() => {
@@ -52,22 +71,7 @@ function Login() {
5271
transport: custom(privyProvider),
5372
});
5473

55-
const signer: Identity.Signer = {
56-
getAddress: async () => {
57-
const [address] = await walletClient.getAddresses();
58-
return address;
59-
},
60-
signMessage: async (message: string) => {
61-
if (embeddedWallet.walletClientType === 'privy') {
62-
const { signature } = await signMessage({ message });
63-
return signature;
64-
}
65-
const [address] = await walletClient.getAddresses();
66-
return await walletClient.signMessage({ account: address, message });
67-
},
68-
};
69-
70-
await hypergraphLogin(signer);
74+
await hypergraphLogin(walletClient, embeddedWallet);
7175
navigate({ to: '/' });
7276
} catch (error) {
7377
alert('Failed to login');
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
import mainVotingAbi from './abis/MainVotingPlugin.json' with { type: 'json' };
2+
import personalSpaceAdminAbi from './abis/PersonalSpaceAdminPlugin.json' with { type: 'json' };
3+
4+
export { mainVotingAbi, personalSpaceAdminAbi };
5+
16
// Simplified ABI for the Safe Module Manager with the functions we need
27
export const safeModuleManagerAbi = [
38
{
@@ -155,8 +160,3 @@ export const daoFactoryAbi = [
155160
type: 'function',
156161
},
157162
] as const;
158-
159-
import mainVotingAbi from './abis/MainVotingPlugin.json' with { type: 'json' };
160-
import personalSpaceAdminAbi from './abis/PersonalSpaceAdminPlugin.json' with { type: 'json' };
161-
162-
export { mainVotingAbi, personalSpaceAdminAbi };

packages/hypergraph/src/identity/abis/MainVotingPlugin.json renamed to packages/hypergraph/src/connect/abis/MainVotingPlugin.json

File renamed without changes.

packages/hypergraph/src/identity/abis/PersonalSpaceAdminPlugin.json renamed to packages/hypergraph/src/connect/abis/PersonalSpaceAdminPlugin.json

File renamed without changes.

packages/hypergraph/src/connect/identity-encryption.ts

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ const signatureMessage = (nonce: Uint8Array): string => {
6767

6868
export const encryptIdentity = async (
6969
signer: Signer,
70-
accountAddress: string,
7170
keys: IdentityKeys,
7271
): Promise<{ ciphertext: string; nonce: string }> => {
7372
const nonce = randomBytes(32);
@@ -76,7 +75,7 @@ export const encryptIdentity = async (
7675

7776
// Check that the signature is valid
7877
const valid = await verifyMessage({
79-
address: accountAddress as Hex,
78+
address: (await signer.getAddress()) as Hex,
8079
message,
8180
signature,
8281
});
@@ -97,18 +96,13 @@ export const encryptIdentity = async (
9796
return { ciphertext, nonce: bytesToHex(nonce) };
9897
};
9998

100-
export const decryptIdentity = async (
101-
signer: Signer,
102-
accountAddress: string,
103-
ciphertext: string,
104-
nonce: string,
105-
): Promise<IdentityKeys> => {
99+
export const decryptIdentity = async (signer: Signer, ciphertext: string, nonce: string): Promise<IdentityKeys> => {
106100
const message = signatureMessage(hexToBytes(nonce));
107101
const signature = (await signer.signMessage(message)) as Hex;
108102

109103
// Check that the signature is valid
110104
const valid = await verifyMessage({
111-
address: accountAddress as Hex,
105+
address: (await signer.getAddress()) as Hex,
112106
message,
113107
signature,
114108
});
@@ -152,7 +146,7 @@ export const encryptAppIdentity = async (
152146

153147
// Check that the signature is valid
154148
const valid = await verifyMessage({
155-
address: accountAddress as Hex,
149+
address: (await signer.getAddress()) as Hex,
156150
message,
157151
signature,
158152
});
@@ -163,6 +157,7 @@ export const encryptAppIdentity = async (
163157
// We use a simple plaintext encoding:
164158
// Hex keys separated by newlines
165159
const keysTxt = [
160+
accountAddress,
166161
keys.encryptionPublicKey,
167162
keys.encryptionPrivateKey,
168163
keys.signaturePublicKey,
@@ -214,6 +209,7 @@ export const decryptAppIdentity = async (
214209
}
215210
const keysTxt = new TextDecoder().decode(keysMsg);
216211
const [
212+
accountAddress,
217213
encryptionPublicKey,
218214
encryptionPrivateKey,
219215
signaturePublicKey,
@@ -222,6 +218,7 @@ export const decryptAppIdentity = async (
222218
appIdentityAddressPrivateKey,
223219
] = keysTxt.split('\n');
224220
return {
221+
accountAddress,
225222
encryptionPublicKey,
226223
encryptionPrivateKey,
227224
signaturePublicKey,

packages/hypergraph/src/connect/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ export * from './login.js';
77
export * from './parse-auth-params.js';
88
export * from './parse-callback-params.js';
99
export * from './prove-ownership.js';
10+
export * from './smart-account.js';
1011
export * from './types.js';

packages/hypergraph/src/connect/login.ts

Lines changed: 38 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import * as Schema from 'effect/Schema';
2-
import type { Address } from 'viem';
2+
import type { Address, Chain, Hex, WalletClient } from 'viem';
33
import * as Messages from '../messages/index.js';
44
import { store } from '../store-connect.js';
5-
import { storeAccountAddress, storeKeys } from './auth-storage.js';
5+
import { loadAccountAddress, storeAccountAddress, storeKeys } from './auth-storage.js';
66
import { createIdentityKeys } from './create-identity-keys.js';
77
import { decryptIdentity, encryptIdentity } from './identity-encryption.js';
88
import { proveIdentityOwnership } from './prove-ownership.js';
9+
import { getSmartAccountWalletClient } from './smart-account.js';
910
import type { IdentityKeys, Signer, Storage } from './types.js';
1011

1112
export async function identityExists(accountAddress: string, syncServerUri: string) {
@@ -23,11 +24,11 @@ export async function signup(
2324
identityToken: string,
2425
) {
2526
const keys = createIdentityKeys();
26-
const { ciphertext, nonce } = await encryptIdentity(signer, accountAddress, keys);
27+
const { ciphertext, nonce } = await encryptIdentity(signer, keys);
2728
const { accountProof, keyProof } = await proveIdentityOwnership(signer, accountAddress, keys);
2829

2930
const req: Messages.RequestConnectCreateIdentity = {
30-
keyBox: { accountAddress, ciphertext, nonce },
31+
keyBox: { signer: await signer.getAddress(), accountAddress, ciphertext, nonce },
3132
accountProof,
3233
keyProof,
3334
signaturePublicKey: keys.signaturePublicKey,
@@ -49,7 +50,6 @@ export async function signup(
4950
if (!decoded.success) {
5051
throw new Error('Error creating identity');
5152
}
52-
storeAccountAddress(storage, accountAddress);
5353
storeKeys(storage, accountAddress, keys);
5454

5555
return {
@@ -69,6 +69,7 @@ export async function restoreKeys(
6969
method: 'POST',
7070
headers: {
7171
'privy-id-token': identityToken,
72+
'account-address': accountAddress,
7273
'Content-Type': 'application/json',
7374
},
7475
});
@@ -77,7 +78,7 @@ export async function restoreKeys(
7778
const decoded = Schema.decodeUnknownSync(Messages.ResponseIdentityEncrypted)(await res.json());
7879
const { keyBox } = decoded;
7980
const { ciphertext, nonce } = keyBox;
80-
const keys = await decryptIdentity(signer, accountAddress, ciphertext, nonce);
81+
const keys = await decryptIdentity(signer, ciphertext, nonce);
8182
storeKeys(storage, accountAddress, keys);
8283
return {
8384
accountAddress,
@@ -87,13 +88,37 @@ export async function restoreKeys(
8788
throw new Error(`Error fetching identity ${res.status}`);
8889
}
8990

90-
export async function login(
91-
signer: Signer,
92-
accountAddress: Address,
93-
syncServerUri: string,
94-
storage: Storage,
95-
identityToken: string,
96-
) {
91+
export async function login({
92+
walletClient,
93+
signer,
94+
syncServerUri,
95+
storage,
96+
identityToken,
97+
rpcUrl,
98+
chain,
99+
}: {
100+
walletClient: WalletClient;
101+
signer: Signer;
102+
syncServerUri: string;
103+
storage: Storage;
104+
identityToken: string;
105+
rpcUrl: string;
106+
chain: Chain;
107+
}) {
108+
const accountAddressFromStorage = (loadAccountAddress(storage) as Hex) ?? undefined;
109+
const smartAccountWalletClient = await getSmartAccountWalletClient({
110+
owner: walletClient,
111+
address: accountAddressFromStorage,
112+
rpcUrl,
113+
chain,
114+
});
115+
if (!smartAccountWalletClient.account) {
116+
throw new Error('Smart account wallet client not found');
117+
}
118+
const accountAddress = smartAccountWalletClient.account.address;
119+
if (accountAddressFromStorage === undefined) {
120+
storeAccountAddress(storage, accountAddress);
121+
}
97122
// const keys = loadKeys(storage, accountAddress);
98123
let authData: {
99124
accountAddress: Address;

0 commit comments

Comments
 (0)