1
- import { MULTIKEY_SIGNER_ADDRESSES , TIME_FRAME_POLICY_ADDRESSES } from './SmartSessionUtil'
2
- import type { Session , ChainSession , Account , ActionData } from '@rhinestone/module-sdk'
1
+ import {
2
+ MOCK_POLICY ,
3
+ MULTIKEY_SIGNER_ADDRESSES ,
4
+ TIME_FRAME_POLICY_ADDRESSES
5
+ } from './SmartSessionUtil'
6
+ import type { Session , ChainSession , Account , ActionData , PolicyData } from '@rhinestone/module-sdk'
3
7
const {
4
8
SMART_SESSIONS_ADDRESS ,
5
9
SmartSessionMode,
@@ -28,10 +32,12 @@ import {
28
32
MultiKeySigner ,
29
33
Permission ,
30
34
Signer ,
31
- WalletGrantPermissionsRequest ,
35
+ SmartSessionGrantPermissionsRequest ,
32
36
ContractCallPermission ,
33
- SignerKeyType
34
- } from '@/data/EIP7715Data'
37
+ NativeTokenRecurringAllowancePermission ,
38
+ ERC20RecurringAllowancePermission
39
+ } from '@reown/appkit-experimental/smart-session'
40
+ import { SignerKeyType } from '@/data/EIP7715Data'
35
41
36
42
// Constants for error messages
37
43
const ERROR_MESSAGES = {
@@ -76,7 +82,7 @@ async function fetchSessionData(
76
82
account : Account ,
77
83
session : Session
78
84
) : Promise < { sessionNonce : bigint ; sessionDigest : Hex ; permissionId : Hex } > {
79
- const permissionId = ( await getPermissionId ( { client : publicClient , session } ) ) as Hex
85
+ const permissionId = ( await getPermissionId ( { session } ) ) as Hex
80
86
const sessionNonce = await getSessionNonce ( { client : publicClient , account, permissionId } )
81
87
const sessionDigest = await getSessionDigest ( {
82
88
client : publicClient ,
@@ -104,14 +110,11 @@ export async function getContext(
104
110
{
105
111
account,
106
112
grantPermissionsRequest
107
- } : { account : Account ; grantPermissionsRequest : WalletGrantPermissionsRequest }
113
+ } : { account : Account ; grantPermissionsRequest : SmartSessionGrantPermissionsRequest }
108
114
) : Promise < Hex > {
109
115
if ( ! walletClient . account ) throw new Error ( ERROR_MESSAGES . ACCOUNT_UNDEFINED )
110
116
111
117
const { chainId : hexChainId } = grantPermissionsRequest
112
- console . log ( 'walletClient.chain:' , walletClient . chain )
113
- console . log ( 'publicClient.chain:' , publicClient . chain )
114
- console . log ( 'hexChainId:' , hexChainId )
115
118
if ( ! walletClient . chain || ! publicClient . chain || ! hexChainId )
116
119
throw new Error ( ERROR_MESSAGES . CHAIN_UNDEFINED )
117
120
if ( toHex ( walletClient . chain . id ) !== hexChainId || toHex ( publicClient . chain . id ) !== hexChainId )
@@ -204,25 +207,25 @@ const adjustVInSignature = (
204
207
}
205
208
206
209
/**
207
- * This method transforms the WalletGrantPermissionsRequest into a Session object
210
+ * This method transforms the SmartSessionGrantPermissionsRequest into a Session object
208
211
* The Session object includes permittied actions and policies.
209
212
* It also includes the Session Validator Address(MultiKeySigner module) and Init Data needed for setting up the module.
210
- * @param WalletGrantPermissionsRequest
213
+ * @param SmartSessionGrantPermissionsRequest
211
214
* @returns
212
215
*/
213
216
function getSmartSession ( {
214
217
chainId,
215
218
expiry,
216
219
permissions,
217
220
signer
218
- } : WalletGrantPermissionsRequest ) : Session {
221
+ } : SmartSessionGrantPermissionsRequest ) : Session {
219
222
const chainIdNumber = parseInt ( chainId , 16 )
220
223
const actions = getActionsFromPermissions ( permissions , chainIdNumber , expiry )
221
-
222
224
const sessionValidator = getSessionValidatorAddress ( signer , chainIdNumber )
223
225
const sessionValidatorInitData = getSessionValidatorInitData ( signer )
224
226
225
227
return {
228
+ chainId : BigInt ( chainId ) ,
226
229
sessionValidator,
227
230
sessionValidatorInitData,
228
231
salt : SESSION_SALT ,
@@ -309,13 +312,23 @@ function isContractCallPermission(permission: Permission): permission is Contrac
309
312
return permission . type === 'contract-call'
310
313
}
311
314
315
+ function isNativeTokenRecurringAllowancePermission (
316
+ permission : Permission
317
+ ) : permission is NativeTokenRecurringAllowancePermission {
318
+ return permission . type === 'native-token-recurring-allowance'
319
+ }
320
+
321
+ function isERC20RecurringAllowancePermission (
322
+ permission : Permission
323
+ ) : permission is ERC20RecurringAllowancePermission {
324
+ return permission . type === 'erc20-recurring-allowance'
325
+ }
326
+
312
327
/**
313
328
* This method processes the permissions array from the permissions request and returns the actions array
314
- * Note - Currently only 'contract-call' permission type is supported
315
- * - For each contract-call permission, it creates an action for each function in the permission
329
+ * Note - For each permission, it creates an action data
316
330
* - It also adds the TIME_FRAME_POLICY for each action as the actionPolicy
317
331
* - The expiry time indicated in the permissions request is used as the expiry time for the actions
318
- * - Function Arguments are not supported in this version
319
332
* @param permissions - Permissions array from the permissions request
320
333
* @param chainId - Chain ID on which the actions are to be performed
321
334
* @param expiry - Expiry time for the actions
@@ -327,12 +340,21 @@ function getActionsFromPermissions(
327
340
expiry : number
328
341
) : ActionData [ ] {
329
342
return permissions . reduce ( ( actions : ActionData [ ] , permission ) => {
330
- if ( ! isContractCallPermission ( permission ) ) {
331
- throw new Error ( ERROR_MESSAGES . UNSUPPORTED_PERMISSION_TYPE ( JSON . stringify ( permission ) ) )
332
- }
343
+ switch ( true ) {
344
+ case isContractCallPermission ( permission ) :
345
+ actions . push (
346
+ ...createActionForContractCall ( permission as ContractCallPermission , chainId , expiry )
347
+ )
348
+ break
349
+
350
+ case isNativeTokenRecurringAllowancePermission ( permission ) :
351
+ case isERC20RecurringAllowancePermission ( permission ) :
352
+ actions . push ( ...createFallbackActionData ( permission , chainId , expiry ) )
353
+ break
333
354
334
- const contractCallActions = createActionForContractCall ( permission , chainId , expiry )
335
- actions . push ( ...contractCallActions )
355
+ default :
356
+ throw new Error ( ERROR_MESSAGES . UNSUPPORTED_PERMISSION_TYPE ( JSON . stringify ( permission ) ) )
357
+ }
336
358
337
359
return actions
338
360
} , [ ] )
@@ -372,3 +394,29 @@ function createActionForContractCall(
372
394
}
373
395
} )
374
396
}
397
+
398
+ /**
399
+ * This is a fallback action data which will be used to skip the functionSelector and address check.
400
+ * */
401
+ function createFallbackActionData (
402
+ permission : Permission ,
403
+ chainId : number ,
404
+ expiry : number
405
+ ) : ActionData [ ] {
406
+ const fallbackActionSelector = '0x00000001'
407
+ const fallbackActionAddress = '0x0000000000000000000000000000000000000001'
408
+
409
+ return [
410
+ {
411
+ actionTarget : fallbackActionAddress ,
412
+ actionTargetSelector : fallbackActionSelector ,
413
+ // Need atleast 1 actionPolicy, so hardcoding the TIME_FRAME_POLICY for now
414
+ actionPolicies : [
415
+ {
416
+ policy : TIME_FRAME_POLICY_ADDRESSES [ chainId ] ,
417
+ initData : encodePacked ( [ 'uint128' , 'uint128' ] , [ BigInt ( expiry ) , BigInt ( 0 ) ] )
418
+ }
419
+ ]
420
+ }
421
+ ]
422
+ }
0 commit comments