1
1
import * as Schema from 'effect/Schema' ;
2
2
import type { SmartAccountClient } from 'permissionless' ;
3
3
import type { Address , Chain , Hex , WalletClient } from 'viem' ;
4
+ import { privateKeyToAccount } from 'viem/accounts' ;
4
5
import { proveIdentityOwnership } from '../identity/prove-ownership.js' ;
5
6
import * as Messages from '../messages/index.js' ;
6
7
import { store } from '../store-connect.js' ;
7
- import { loadAccountAddress , storeAccountAddress , storeKeys , wipeAccountAddress } from './auth-storage.js' ;
8
+ import { loadAccountAddress , storeAccountAddress , storeKeys } from './auth-storage.js' ;
8
9
import { createIdentityKeys } from './create-identity-keys.js' ;
9
10
import { decryptIdentity , encryptIdentity } from './identity-encryption.js' ;
10
11
import {
11
12
type SmartAccountParams ,
13
+ addSmartAccountOwner ,
12
14
getSmartAccountWalletClient ,
13
15
isSmartAccountDeployed ,
14
16
smartAccountNeedsUpdate ,
@@ -29,17 +31,26 @@ export async function signup(
29
31
smartAccountClient : SmartAccountClient ,
30
32
accountAddress : Address ,
31
33
syncServerUri : string ,
32
- storage : Storage ,
34
+ addressStorage : Storage ,
35
+ keysStorage : Storage ,
33
36
identityToken : string ,
37
+ chain : Chain ,
38
+ rpcUrl : string ,
34
39
) {
35
40
const keys = createIdentityKeys ( ) ;
36
41
const { ciphertext, nonce } = await encryptIdentity ( signer , keys ) ;
37
- const { accountProof, keyProof } = await proveIdentityOwnership (
38
- walletClient ,
39
- smartAccountClient ,
40
- accountAddress ,
41
- keys ,
42
- ) ;
42
+
43
+ const localAccount = privateKeyToAccount ( keys . signaturePrivateKey as `0x${string } `) ;
44
+ // This will deploy the smart account if it's not deployed
45
+ await addSmartAccountOwner ( smartAccountClient , localAccount . address , chain , rpcUrl ) ;
46
+ const localSmartAccountClient = await getSmartAccountWalletClient ( {
47
+ owner : localAccount ,
48
+ address : accountAddress ,
49
+ rpcUrl,
50
+ chain,
51
+ } ) ;
52
+
53
+ const { accountProof, keyProof } = await proveIdentityOwnership ( localSmartAccountClient , accountAddress , keys ) ;
43
54
44
55
const req : Messages . RequestConnectCreateIdentity = {
45
56
keyBox : { signer : await signer . getAddress ( ) , accountAddress, ciphertext, nonce } ,
@@ -64,8 +75,8 @@ export async function signup(
64
75
if ( ! decoded . success ) {
65
76
throw new Error ( 'Error creating identity' ) ;
66
77
}
67
- storeKeys ( storage , accountAddress , keys ) ;
68
- storeAccountAddress ( storage , accountAddress ) ;
78
+ storeKeys ( keysStorage , accountAddress , keys ) ;
79
+ storeAccountAddress ( addressStorage , accountAddress ) ;
69
80
return {
70
81
accountAddress,
71
82
keys,
@@ -76,7 +87,8 @@ export async function restoreKeys(
76
87
signer : Signer ,
77
88
accountAddress : Address ,
78
89
syncServerUri : string ,
79
- storage : Storage ,
90
+ addressStorage : Storage ,
91
+ keysStorage : Storage ,
80
92
identityToken : string ,
81
93
) {
82
94
const res = await fetch ( new URL ( '/connect/identity/encrypted' , syncServerUri ) , {
@@ -93,8 +105,8 @@ export async function restoreKeys(
93
105
const { keyBox } = decoded ;
94
106
const { ciphertext, nonce } = keyBox ;
95
107
const keys = await decryptIdentity ( signer , ciphertext , nonce ) ;
96
- storeKeys ( storage , accountAddress , keys ) ;
97
- storeAccountAddress ( storage , accountAddress ) ;
108
+ storeKeys ( keysStorage , accountAddress , keys ) ;
109
+ storeAccountAddress ( addressStorage , accountAddress ) ;
98
110
return {
99
111
accountAddress,
100
112
keys,
@@ -103,8 +115,13 @@ export async function restoreKeys(
103
115
throw new Error ( `Error fetching identity ${ res . status } ` ) ;
104
116
}
105
117
106
- const getAndDeploySmartAccount = async ( walletClient : WalletClient , rpcUrl : string , chain : Chain , storage : Storage ) => {
107
- const accountAddressFromStorage = loadAccountAddress ( storage ) as Hex ;
118
+ const getAndUpdateSmartAccount = async (
119
+ walletClient : WalletClient ,
120
+ rpcUrl : string ,
121
+ chain : Chain ,
122
+ addressStorage : Storage ,
123
+ ) => {
124
+ const accountAddressFromStorage = loadAccountAddress ( addressStorage ) as Hex ;
108
125
const smartAccountParams : SmartAccountParams = {
109
126
owner : walletClient ,
110
127
rpcUrl,
@@ -128,53 +145,34 @@ const getAndDeploySmartAccount = async (walletClient: WalletClient, rpcUrl: stri
128
145
// Create the client again to ensure we have the 7579 config now
129
146
return getSmartAccountWalletClient ( smartAccountParams ) ;
130
147
}
131
- if ( ! ( await isSmartAccountDeployed ( smartAccountWalletClient ) ) ) {
132
- // TODO: remove this once we manage to get counterfactual signatures working
133
- console . log ( 'sending dummy userOp to deploy smart account' ) ;
134
- if ( ! walletClient . account ) {
135
- throw new Error ( 'Wallet client account not found' ) ;
136
- }
137
- const tx = await smartAccountWalletClient . sendUserOperation ( {
138
- calls : [ { to : walletClient . account . address , data : '0x' } ] ,
139
- account : smartAccountWalletClient . account ,
140
- } ) ;
141
-
142
- console . log ( 'tx' , tx ) ;
143
- const receipt = await smartAccountWalletClient . waitForUserOperationReceipt ( { hash : tx } ) ;
144
- console . log ( 'receipt' , receipt ) ;
145
- }
146
148
return smartAccountWalletClient ;
147
149
} ;
148
150
149
151
export async function login ( {
150
152
walletClient,
151
153
signer,
152
154
syncServerUri,
153
- storage,
155
+ addressStorage,
156
+ keysStorage,
154
157
identityToken,
155
158
rpcUrl,
156
159
chain,
157
160
} : {
158
161
walletClient : WalletClient ;
159
162
signer : Signer ;
160
163
syncServerUri : string ;
161
- storage : Storage ;
164
+ addressStorage : Storage ;
165
+ keysStorage : Storage ;
162
166
identityToken : string ;
163
167
rpcUrl : string ;
164
168
chain : Chain ;
165
169
} ) {
166
- let smartAccountWalletClient : SmartAccountClient ;
167
- try {
168
- smartAccountWalletClient = await getAndDeploySmartAccount ( walletClient , rpcUrl , chain , storage ) ;
169
- } catch ( error ) {
170
- wipeAccountAddress ( storage ) ;
171
- smartAccountWalletClient = await getAndDeploySmartAccount ( walletClient , rpcUrl , chain , storage ) ;
172
- }
170
+ const smartAccountWalletClient = await getAndUpdateSmartAccount ( walletClient , rpcUrl , chain , addressStorage ) ;
173
171
if ( ! smartAccountWalletClient . account ) {
174
172
throw new Error ( 'Smart account wallet client account not found' ) ;
175
173
}
176
174
const accountAddress = smartAccountWalletClient . account . address ;
177
- // const keys = loadKeys(storage, accountAddress);
175
+
178
176
let authData : {
179
177
accountAddress : Address ;
180
178
keys : IdentityKeys ;
@@ -187,11 +185,14 @@ export async function login({
187
185
smartAccountWalletClient ,
188
186
accountAddress ,
189
187
syncServerUri ,
190
- storage ,
188
+ addressStorage ,
189
+ keysStorage ,
191
190
identityToken ,
191
+ chain ,
192
+ rpcUrl ,
192
193
) ;
193
194
} else {
194
- authData = await restoreKeys ( signer , accountAddress , syncServerUri , storage , identityToken ) ;
195
+ authData = await restoreKeys ( signer , accountAddress , syncServerUri , addressStorage , keysStorage , identityToken ) ;
195
196
}
196
197
store . send ( { type : 'reset' } ) ;
197
198
store . send ( {
0 commit comments