@@ -31,9 +31,11 @@ import {
3131 type AbiFunction ,
3232 type Account ,
3333 type Address ,
34+ type Calls ,
3435 type Chain ,
3536 ContractFunctionExecutionError ,
3637 type Hex ,
38+ type Narrow ,
3739 type SignableMessage ,
3840 type WalletClient ,
3941 createPublicClient ,
@@ -57,6 +59,7 @@ import {
5759 personalSpaceAdminAbi ,
5860 safe7579Abi ,
5961 safeModuleManagerAbi ,
62+ safeOwnerManagerAbi ,
6063 smartSessionsAbi ,
6164} from './abis.js' ;
6265
@@ -171,11 +174,13 @@ export type SmartSessionClient = {
171174// by this function is deployed, it means it might need to be updated to have the 7579 module installed
172175const getLegacySmartAccountWalletClient = async ( {
173176 owner,
177+ address,
174178 chain = GEOGENESIS ,
175179 rpcUrl = DEFAULT_RPC_URL ,
176180 apiKey = DEFAULT_API_KEY ,
177181} : {
178182 owner : WalletClient | Account ;
183+ address ?: Hex ;
179184 chain ?: Chain ;
180185 rpcUrl ?: string ;
181186 apiKey ?: string ;
@@ -186,21 +191,19 @@ const getLegacySmartAccountWalletClient = async ({
186191 chain,
187192 } ) ;
188193
189- console . log ( 'owner' , owner ) ;
190- console . log ( 'publicClient' , publicClient ) ;
191- console . log ( 'chain' , chain ) ;
192- console . log ( 'rpcUrl' , rpcUrl ) ;
193- console . log ( 'apiKey' , apiKey ) ;
194- const safeAccount = await toSafeSmartAccount ( {
194+ const safeAccountParams : ToSafeSmartAccountParameters < '0.7' , Hex > = {
195195 client : publicClient ,
196196 owners : [ owner ] ,
197197 entryPoint : {
198- // optional, defaults to 0.7
199198 address : entryPoint07Address ,
200199 version : '0.7' ,
201200 } ,
202201 version : '1.4.1' ,
203- } ) ;
202+ } ;
203+ if ( address ) {
204+ safeAccountParams . address = address ;
205+ }
206+ const safeAccount = await toSafeSmartAccount ( safeAccountParams ) ;
204207
205208 const bundlerTransport = http ( `${ BUNDLER_TRANSPORT_URL_BASE } ${ chain . id } /rpc?apikey=${ apiKey } ` ) ;
206209 const paymasterClient = createPimlicoClient ( {
@@ -343,6 +346,16 @@ export const getSmartAccountWalletClient = async ({
343346 rpcUrl = DEFAULT_RPC_URL ,
344347 apiKey = DEFAULT_API_KEY ,
345348} : SmartAccountParams ) : Promise < SmartAccountClient > => {
349+ if ( chain . id === GEO_TESTNET . id ) {
350+ // We don't have the smart sessions module deployed on testnet yet, so we need to use the legacy smart account wallet client
351+ // TODO: remove this once we have the smart sessions module deployed on testnet
352+ const params : SmartAccountParams = { owner, chain, rpcUrl, apiKey } ;
353+ if ( address ) {
354+ params . address = address ;
355+ }
356+ console . log ( 'on testnet, getting legacy smart account wallet client' ) ;
357+ return getLegacySmartAccountWalletClient ( params ) ;
358+ }
346359 if ( address ) {
347360 return get7579SmartAccountWalletClient ( { owner, address, chain, rpcUrl, apiKey } ) ;
348361 }
@@ -412,6 +425,11 @@ export const smartAccountNeedsUpdate = async (
412425 chain : Chain ,
413426 rpcUrl : string ,
414427) : Promise < boolean > => {
428+ if ( chain . id === GEO_TESTNET . id ) {
429+ // We don't have the smart sessions module deployed on testnet yet, so we need to use the legacy smart account wallet client
430+ // TODO: remove this once we have the smart sessions module deployed on testnet
431+ return false ;
432+ }
415433 // If we haven't deployed the smart account, we would always deploy an updated version
416434 if ( ! ( await isSmartAccountDeployed ( smartAccountClient ) ) ) {
417435 return false ;
@@ -430,6 +448,12 @@ export const updateLegacySmartAccount = async (
430448 if ( ! smartAccountClient . account ?. address ) {
431449 throw new Error ( 'Invalid smart account' ) ;
432450 }
451+ if ( chain . id === GEO_TESTNET . id ) {
452+ // We don't have the smart sessions module deployed on testnet yet, so we need to use the legacy smart account wallet client
453+ // TODO: remove this once we have the smart sessions module deployed on testnet
454+ console . log ( 'on testnet, skipping updateLegacySmartAccount' ) ;
455+ return ;
456+ }
433457 const ownableValidator = getOwnableValidator ( {
434458 owners : [ smartAccountClient . account . address ] ,
435459 threshold : 1 ,
@@ -596,6 +620,33 @@ export const createSmartSession = async (
596620 transport,
597621 chain,
598622 } ) ;
623+ if ( chain . id === GEO_TESTNET . id ) {
624+ // We don't have the smart sessions module deployed on testnet yet, so we need to fake it by adding an account owner
625+ // TODO: remove this once we have the smart sessions module deployed on testnet
626+ console . log ( 'on testnet, faking a smart session by adding an account owner' ) ;
627+ const tx = await smartAccountClient . sendUserOperation ( {
628+ calls : [
629+ {
630+ to : smartAccountClient . account . address ,
631+ data : encodeFunctionData ( {
632+ abi : safeOwnerManagerAbi ,
633+ functionName : 'addOwnerWithThreshold' ,
634+ args : [ sessionKeyAccount . address , BigInt ( 1 ) ] ,
635+ } ) ,
636+ value : BigInt ( 0 ) ,
637+ } ,
638+ ] ,
639+ account : smartAccountClient . account ,
640+ } ) ;
641+ const receipt = await smartAccountClient . waitForUserOperationReceipt ( {
642+ hash : tx ,
643+ } ) ;
644+ if ( ! receipt . success ) {
645+ throw new Error ( 'Transaction to add account owner failed' ) ;
646+ }
647+ console . log ( 'account owner added' ) ;
648+ return bytesToHex ( randomBytes ( 32 ) ) as Hex ;
649+ }
599650 // We create a dummy action so that we can execute a userOp immediately and create the session onchain,
600651 // rather than having to pass along all the enable data to the end user app.
601652 // In the future, if we enable attestations with the Rhinestone registry, we can remove this and instead
@@ -768,7 +819,7 @@ export const getSmartSessionClient = async ({
768819} ) : Promise < SmartSessionClient > => {
769820 const sessionKeyAccount = privateKeyToAccount ( sessionPrivateKey ) ;
770821 const smartAccountClient = await getSmartAccountWalletClient ( {
771- owner : sessionKeyAccount , // Won't really be used, but we need to pass in an account
822+ owner : sessionKeyAccount , // Won't really be used (except in testnet) , but we need to pass in an account
772823 address : accountAddress ,
773824 chain,
774825 rpcUrl,
@@ -786,6 +837,14 @@ export const getSmartSessionClient = async ({
786837 if ( ! smartAccountClient . account ) {
787838 throw new Error ( 'Invalid smart account' ) ;
788839 }
840+ if ( chain . id === GEO_TESTNET . id ) {
841+ // We don't have the smart sessions module deployed on testnet yet, so we need to use the legacy smart account wallet client
842+ // TODO: remove this once we have the smart sessions module deployed on testnet
843+ return smartAccountClient . sendUserOperation ( {
844+ calls : calls as Calls < Narrow < calls > > ,
845+ account : smartAccountClient . account ,
846+ } ) ;
847+ }
789848 const account = getAccount ( {
790849 address : smartAccountClient . account . address ,
791850 type : 'safe' ,
0 commit comments