@graphprotocol/hypergraph 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/dist/connect/abis/MainVotingPlugin.json +1865 -0
  2. package/dist/connect/abis/PersonalSpaceAdminPlugin.json +531 -0
  3. package/dist/connect/abis.d.ts +115 -0
  4. package/dist/connect/abis.d.ts.map +1 -0
  5. package/dist/connect/abis.js +141 -0
  6. package/dist/connect/abis.js.map +1 -0
  7. package/dist/connect/auth-storage.d.ts +15 -0
  8. package/dist/connect/auth-storage.js +53 -0
  9. package/dist/connect/auth-storage.js.map +1 -0
  10. package/dist/connect/create-app-identity.d.ts +7 -0
  11. package/dist/connect/create-app-identity.js +15 -0
  12. package/dist/connect/create-app-identity.js.map +1 -0
  13. package/dist/connect/create-auth-url.d.ts +15 -0
  14. package/dist/connect/create-callback-params.d.ts +28 -0
  15. package/dist/connect/create-callback-params.d.ts.map +1 -1
  16. package/dist/connect/create-callback-params.js.map +1 -1
  17. package/dist/connect/create-identity-keys.d.ts +3 -0
  18. package/dist/connect/create-identity-keys.js +20 -0
  19. package/dist/connect/create-identity-keys.js.map +1 -0
  20. package/dist/connect/identity-encryption.d.ts +12 -0
  21. package/dist/connect/identity-encryption.d.ts.map +1 -1
  22. package/dist/connect/identity-encryption.js +187 -0
  23. package/dist/connect/identity-encryption.js.map +1 -0
  24. package/dist/connect/index.d.ts +11 -0
  25. package/dist/connect/index.d.ts.map +1 -1
  26. package/dist/connect/index.js +11 -0
  27. package/dist/connect/index.js.map +1 -0
  28. package/dist/connect/login.d.ts +22 -0
  29. package/dist/connect/login.d.ts.map +1 -1
  30. package/dist/connect/login.js +172 -0
  31. package/dist/connect/login.js.map +1 -0
  32. package/dist/connect/parse-auth-params.d.ts +14 -0
  33. package/dist/connect/parse-auth-params.d.ts.map +1 -0
  34. package/dist/connect/parse-auth-params.js +40 -0
  35. package/dist/connect/parse-auth-params.js.map +1 -0
  36. package/dist/connect/parse-callback-params.d.ts +13 -0
  37. package/dist/connect/parse-callback-params.d.ts.map +1 -1
  38. package/dist/connect/parse-callback-params.js +4 -1
  39. package/dist/connect/parse-callback-params.js.map +1 -1
  40. package/dist/connect/smart-account.d.ts +96 -0
  41. package/dist/connect/smart-account.d.ts.map +1 -0
  42. package/dist/connect/smart-account.js +761 -0
  43. package/dist/connect/smart-account.js.map +1 -0
  44. package/dist/connect/types.d.ts +2 -0
  45. package/dist/connect/types.d.ts.map +1 -1
  46. package/dist/connect/types.js.map +1 -1
  47. package/dist/entity/create.d.ts +8 -0
  48. package/dist/entity/create.js +51 -0
  49. package/dist/entity/create.js.map +1 -0
  50. package/dist/entity/decodedEntitiesCache.d.ts +23 -0
  51. package/dist/entity/decodedEntitiesCache.d.ts.map +1 -1
  52. package/dist/entity/decodedEntitiesCache.js +2 -0
  53. package/dist/entity/decodedEntitiesCache.js.map +1 -0
  54. package/dist/entity/delete.d.ts +12 -0
  55. package/dist/entity/delete.js +44 -0
  56. package/dist/entity/delete.js.map +1 -0
  57. package/dist/entity/entity.d.ts +18 -0
  58. package/dist/entity/entity.js +19 -0
  59. package/dist/entity/entity.js.map +1 -0
  60. package/dist/entity/entityRelationParentsMap.d.ts +4 -0
  61. package/dist/entity/entityRelationParentsMap.js +2 -0
  62. package/dist/entity/entityRelationParentsMap.js.map +1 -0
  63. package/dist/entity/findMany.d.ts +22 -0
  64. package/dist/entity/findMany.d.ts.map +1 -1
  65. package/dist/entity/findMany.js +8 -8
  66. package/dist/entity/findMany.js.map +1 -1
  67. package/dist/entity/findOne.d.ts +8 -0
  68. package/dist/entity/findOne.js +31 -0
  69. package/dist/entity/findOne.js.map +1 -0
  70. package/dist/entity/getEntityRelations.d.ts +4 -0
  71. package/dist/entity/getEntityRelations.d.ts.map +1 -1
  72. package/dist/entity/getEntityRelations.js +35 -0
  73. package/dist/entity/getEntityRelations.js.map +1 -0
  74. package/dist/entity/hasValidTypesProperty.d.ts +2 -0
  75. package/dist/entity/hasValidTypesProperty.d.ts.map +1 -0
  76. package/dist/entity/hasValidTypesProperty.js +4 -0
  77. package/dist/entity/hasValidTypesProperty.js.map +1 -0
  78. package/dist/entity/index.d.ts +9 -0
  79. package/dist/entity/index.js +9 -0
  80. package/dist/entity/index.js.map +1 -0
  81. package/dist/entity/relationParentsMap.d.ts +4 -0
  82. package/dist/entity/relationParentsMap.js +2 -0
  83. package/dist/entity/relationParentsMap.js.map +1 -0
  84. package/dist/entity/removeRelation.d.ts +7 -0
  85. package/dist/entity/removeRelation.js +17 -0
  86. package/dist/entity/removeRelation.js.map +1 -0
  87. package/dist/entity/test.d.ts +2 -0
  88. package/dist/entity/test.d.ts.map +1 -0
  89. package/dist/entity/test.js +2 -0
  90. package/dist/entity/test.js.map +1 -0
  91. package/dist/entity/types.d.ts +8 -8
  92. package/dist/entity/update.d.ts +8 -0
  93. package/dist/entity/update.js +58 -0
  94. package/dist/entity/update.js.map +1 -0
  95. package/dist/entity/variant-schema.d.ts +247 -0
  96. package/dist/entity/variant-schema.d.ts.map +1 -0
  97. package/dist/entity/variant-schema.js +204 -0
  98. package/dist/entity/variant-schema.js.map +1 -0
  99. package/dist/identity/auth-storage.d.ts +6 -0
  100. package/dist/identity/auth-storage.d.ts.map +1 -1
  101. package/dist/identity/auth-storage.js +52 -0
  102. package/dist/identity/auth-storage.js.map +1 -0
  103. package/dist/identity/get-verified-identity.d.ts +7 -0
  104. package/dist/identity/get-verified-identity.d.ts.map +1 -1
  105. package/dist/identity/get-verified-identity.js +37 -0
  106. package/dist/identity/get-verified-identity.js.map +1 -0
  107. package/dist/identity/identity-encryption.d.ts +7 -0
  108. package/dist/identity/identity-encryption.js +120 -0
  109. package/dist/identity/identity-encryption.js.map +1 -0
  110. package/dist/identity/index.d.ts +7 -0
  111. package/dist/identity/index.d.ts.map +1 -1
  112. package/dist/identity/index.js +7 -0
  113. package/dist/identity/index.js.map +1 -0
  114. package/dist/identity/logout.d.ts +3 -0
  115. package/dist/identity/logout.js +9 -0
  116. package/dist/identity/logout.js.map +1 -0
  117. package/dist/identity/prove-ownership.d.ts +15 -0
  118. package/dist/identity/prove-ownership.d.ts.map +1 -1
  119. package/dist/identity/prove-ownership.js +90 -0
  120. package/dist/identity/prove-ownership.js.map +1 -0
  121. package/dist/identity/types.d.ts +37 -0
  122. package/dist/identity/types.d.ts.map +1 -0
  123. package/dist/identity/types.js +11 -0
  124. package/dist/identity/types.js.map +1 -0
  125. package/dist/inboxes/create-inbox.d.ts +22 -0
  126. package/dist/inboxes/create-inbox.js +76 -0
  127. package/dist/inboxes/create-inbox.js.map +1 -0
  128. package/dist/inboxes/get-list-inboxes.d.ts +20 -0
  129. package/dist/inboxes/get-list-inboxes.js +45 -0
  130. package/dist/inboxes/get-list-inboxes.js.map +1 -0
  131. package/dist/inboxes/index.d.ts +11 -0
  132. package/dist/inboxes/index.js +11 -0
  133. package/dist/inboxes/index.js.map +1 -0
  134. package/dist/inboxes/merge-messages.d.ts +6 -0
  135. package/dist/inboxes/merge-messages.js +23 -0
  136. package/dist/inboxes/merge-messages.js.map +1 -0
  137. package/dist/inboxes/message-encryption.d.ts +15 -0
  138. package/dist/inboxes/message-encryption.js +29 -0
  139. package/dist/inboxes/message-encryption.js.map +1 -0
  140. package/dist/inboxes/message-validation.d.ts +6 -0
  141. package/dist/inboxes/message-validation.d.ts.map +1 -1
  142. package/dist/inboxes/message-validation.js +53 -0
  143. package/dist/inboxes/message-validation.js.map +1 -0
  144. package/dist/inboxes/prepare-message.d.ts +2 -2
  145. package/dist/inboxes/prepare-message.js +78 -0
  146. package/dist/inboxes/prepare-message.js.map +1 -0
  147. package/dist/inboxes/recover-inbox-creator.d.ts +5 -0
  148. package/dist/inboxes/recover-inbox-creator.js +24 -0
  149. package/dist/inboxes/recover-inbox-creator.js.map +1 -0
  150. package/dist/inboxes/recover-inbox-message-signer.d.ts +4 -0
  151. package/dist/inboxes/recover-inbox-message-signer.js +32 -0
  152. package/dist/inboxes/recover-inbox-message-signer.js.map +1 -0
  153. package/dist/inboxes/send-message.d.ts +19 -0
  154. package/dist/inboxes/send-message.js +58 -0
  155. package/dist/inboxes/send-message.js.map +1 -0
  156. package/dist/inboxes/types.d.ts +4 -0
  157. package/dist/inboxes/types.d.ts.map +1 -0
  158. package/dist/inboxes/types.js +3 -0
  159. package/dist/inboxes/types.js.map +1 -0
  160. package/dist/index.d.ts +14 -0
  161. package/dist/index.js +14 -0
  162. package/dist/index.js.map +1 -0
  163. package/dist/key/create-key.d.ts +11 -0
  164. package/dist/key/create-key.d.ts.map +1 -0
  165. package/dist/key/create-key.js +22 -0
  166. package/dist/key/create-key.js.map +1 -0
  167. package/dist/key/decrypt-key.d.ts +9 -0
  168. package/dist/key/decrypt-key.d.ts.map +1 -0
  169. package/dist/key/decrypt-key.js +16 -0
  170. package/dist/key/decrypt-key.js.map +1 -0
  171. package/dist/key/encrypt-key.d.ts +11 -0
  172. package/dist/key/encrypt-key.d.ts.map +1 -0
  173. package/dist/key/encrypt-key.js +20 -0
  174. package/dist/key/encrypt-key.js.map +1 -0
  175. package/dist/key/index.d.ts +5 -0
  176. package/dist/key/index.d.ts.map +1 -0
  177. package/dist/key/index.js +5 -0
  178. package/dist/key/index.js.map +1 -0
  179. package/dist/key/key-box.d.ts +19 -0
  180. package/dist/key/key-box.d.ts.map +1 -0
  181. package/dist/key/key-box.js +38 -0
  182. package/dist/key/key-box.js.map +1 -0
  183. package/dist/messages/decrypt-message.d.ts +7 -0
  184. package/dist/messages/decrypt-message.d.ts.map +1 -0
  185. package/dist/messages/decrypt-message.js +11 -0
  186. package/dist/messages/decrypt-message.js.map +1 -0
  187. package/dist/messages/encrypt-message.d.ts +7 -0
  188. package/dist/messages/encrypt-message.d.ts.map +1 -0
  189. package/dist/messages/encrypt-message.js +12 -0
  190. package/dist/messages/encrypt-message.js.map +1 -0
  191. package/dist/messages/index.d.ts +6 -0
  192. package/dist/messages/index.js +6 -0
  193. package/dist/messages/index.js.map +1 -0
  194. package/dist/messages/serialize.d.ts +3 -0
  195. package/dist/messages/serialize.d.ts.map +1 -0
  196. package/dist/messages/serialize.js +30 -0
  197. package/dist/messages/serialize.js.map +1 -0
  198. package/dist/messages/signed-update-message.d.ts +23 -0
  199. package/dist/messages/signed-update-message.js +56 -0
  200. package/dist/messages/signed-update-message.js.map +1 -0
  201. package/dist/messages/types.d.ts +1268 -0
  202. package/dist/messages/types.d.ts.map +1 -1
  203. package/dist/messages/types.js +312 -0
  204. package/dist/messages/types.js.map +1 -0
  205. package/dist/space-events/accept-invitation.d.ts +9 -0
  206. package/dist/space-events/accept-invitation.js +28 -0
  207. package/dist/space-events/accept-invitation.js.map +1 -0
  208. package/dist/space-events/apply-event.d.ts +11 -0
  209. package/dist/space-events/apply-event.js +130 -0
  210. package/dist/space-events/apply-event.js.map +1 -0
  211. package/dist/space-events/create-inbox.d.ts +14 -0
  212. package/dist/space-events/create-inbox.js +41 -0
  213. package/dist/space-events/create-inbox.js.map +1 -0
  214. package/dist/space-events/create-invitation.d.ts +12 -0
  215. package/dist/space-events/create-invitation.js +30 -0
  216. package/dist/space-events/create-invitation.js.map +1 -0
  217. package/dist/space-events/create-space.d.ts +9 -0
  218. package/dist/space-events/create-space.js +29 -0
  219. package/dist/space-events/create-space.js.map +1 -0
  220. package/dist/space-events/delete-space.d.ts +10 -0
  221. package/dist/space-events/delete-space.js +30 -0
  222. package/dist/space-events/delete-space.js.map +1 -0
  223. package/dist/space-events/hash-event.d.ts +3 -0
  224. package/dist/space-events/hash-event.js +7 -0
  225. package/dist/space-events/hash-event.js.map +1 -0
  226. package/dist/space-events/index.d.ts +9 -0
  227. package/dist/space-events/index.js +9 -0
  228. package/dist/space-events/index.js.map +1 -0
  229. package/dist/space-events/types.d.ts +222 -0
  230. package/dist/space-events/types.d.ts.map +1 -0
  231. package/dist/space-events/types.js +102 -0
  232. package/dist/space-events/types.js.map +1 -0
  233. package/dist/space-info/decrypt-space-info.d.ts +7 -0
  234. package/dist/space-info/decrypt-space-info.js +18 -0
  235. package/dist/space-info/decrypt-space-info.js.map +1 -0
  236. package/dist/space-info/encrypt-and-sign-space-info.d.ts +17 -0
  237. package/dist/space-info/encrypt-and-sign-space-info.js +39 -0
  238. package/dist/space-info/encrypt-and-sign-space-info.js.map +1 -0
  239. package/dist/space-info/index.d.ts +4 -0
  240. package/dist/space-info/index.js +4 -0
  241. package/dist/space-info/index.js.map +1 -0
  242. package/dist/space-info/types.d.ts +6 -0
  243. package/dist/space-info/types.d.ts.map +1 -0
  244. package/dist/space-info/types.js +5 -0
  245. package/dist/space-info/types.js.map +1 -0
  246. package/dist/store-connect.d.ts +149 -0
  247. package/dist/store-connect.d.ts.map +1 -1
  248. package/dist/store-connect.js +289 -0
  249. package/dist/store-connect.js.map +1 -0
  250. package/dist/store.d.ts +158 -0
  251. package/dist/store.d.ts.map +1 -1
  252. package/dist/store.js +354 -0
  253. package/dist/store.js.map +1 -0
  254. package/dist/type/type.d.ts +14 -0
  255. package/dist/type/type.d.ts.map +1 -1
  256. package/dist/type/type.js +25 -0
  257. package/dist/type/type.js.map +1 -0
  258. package/dist/types.d.ts +80 -0
  259. package/dist/types.d.ts.map +1 -0
  260. package/dist/types.js +37 -0
  261. package/dist/types.js.map +1 -0
  262. package/dist/utils/assertExhaustive.d.ts +2 -0
  263. package/dist/utils/assertExhaustive.d.ts.map +1 -0
  264. package/dist/utils/assertExhaustive.js +4 -0
  265. package/dist/utils/assertExhaustive.js.map +1 -0
  266. package/dist/utils/automergeId.d.ts +1 -1
  267. package/dist/utils/automergeId.d.ts.map +1 -1
  268. package/dist/utils/automergeId.js +1 -1
  269. package/dist/utils/automergeId.js.map +1 -1
  270. package/dist/utils/base58.d.ts +36 -0
  271. package/dist/utils/base58.d.ts.map +1 -0
  272. package/dist/utils/base58.js +62 -0
  273. package/dist/utils/base58.js.map +1 -0
  274. package/dist/utils/hexBytesAddressUtils.d.ts +4 -0
  275. package/dist/utils/hexBytesAddressUtils.d.ts.map +1 -0
  276. package/dist/utils/hexBytesAddressUtils.js +21 -0
  277. package/dist/utils/hexBytesAddressUtils.js.map +1 -0
  278. package/dist/utils/index.d.ts +9 -0
  279. package/dist/utils/index.js +9 -0
  280. package/dist/utils/index.js.map +1 -0
  281. package/dist/utils/internal/base58Utils.d.ts +4 -0
  282. package/dist/utils/internal/base58Utils.d.ts.map +1 -0
  283. package/dist/utils/internal/base58Utils.js +40 -0
  284. package/dist/utils/internal/base58Utils.js.map +1 -0
  285. package/dist/utils/internal/deep-merge.d.ts +7 -0
  286. package/dist/utils/internal/deep-merge.d.ts.map +1 -0
  287. package/dist/utils/internal/deep-merge.js +33 -0
  288. package/dist/utils/internal/deep-merge.js.map +1 -0
  289. package/dist/utils/isRelationField.d.ts +3 -0
  290. package/dist/utils/isRelationField.d.ts.map +1 -0
  291. package/dist/utils/isRelationField.js +8 -0
  292. package/dist/utils/isRelationField.js.map +1 -0
  293. package/dist/utils/jsc.d.ts +49 -0
  294. package/dist/utils/jsc.d.ts.map +1 -0
  295. package/dist/utils/jsc.js +88 -0
  296. package/dist/utils/jsc.js.map +1 -0
  297. package/dist/utils/stringToUint8Array.d.ts +3 -0
  298. package/dist/utils/stringToUint8Array.d.ts.map +1 -0
  299. package/dist/utils/stringToUint8Array.js +9 -0
  300. package/dist/utils/stringToUint8Array.js.map +1 -0
  301. package/package.json +5 -2
  302. package/src/connect/abis/MainVotingPlugin.json +1865 -0
  303. package/src/connect/abis/PersonalSpaceAdminPlugin.json +531 -0
  304. package/src/connect/abis.ts +183 -0
  305. package/src/connect/create-callback-params.ts +4 -1
  306. package/src/connect/identity-encryption.ts +10 -14
  307. package/src/connect/index.ts +1 -1
  308. package/src/connect/login.ts +106 -18
  309. package/src/connect/parse-callback-params.ts +4 -1
  310. package/src/connect/smart-account.ts +915 -0
  311. package/src/connect/types.ts +2 -0
  312. package/src/entity/decodedEntitiesCache.ts +1 -1
  313. package/src/entity/findMany.ts +16 -14
  314. package/src/entity/getEntityRelations.ts +1 -1
  315. package/src/entity/types.ts +8 -8
  316. package/src/identity/auth-storage.ts +11 -1
  317. package/src/identity/get-verified-identity.ts +6 -1
  318. package/src/identity/index.ts +1 -1
  319. package/src/identity/prove-ownership.ts +52 -8
  320. package/src/inboxes/message-validation.ts +17 -2
  321. package/src/messages/types.ts +6 -0
  322. package/src/store-connect.ts +1 -52
  323. package/src/store.ts +78 -48
  324. package/src/type/type.ts +4 -2
  325. package/src/types.ts +19 -1
  326. package/src/utils/automergeId.ts +1 -1
  327. package/dist/connect/prove-ownership.d.ts.map +0 -1
  328. package/src/connect/prove-ownership.ts +0 -58
@@ -0,0 +1,915 @@
1
+ import { MAINNET, TESTNET } from '@graphprotocol/grc-20/contracts';
2
+ import { randomBytes } from '@noble/hashes/utils';
3
+ import {
4
+ OWNABLE_VALIDATOR_ADDRESS,
5
+ RHINESTONE_ATTESTER_ADDRESS,
6
+ type Session,
7
+ SmartSessionMode,
8
+ encodeSmartSessionSignature,
9
+ encodeValidationData,
10
+ encodeValidatorNonce,
11
+ getAccount,
12
+ getEnableSessionDetails,
13
+ getOwnableValidator,
14
+ getOwnableValidatorMockSignature,
15
+ getPermissionId,
16
+ getSmartSessionsValidator,
17
+ getSpendingLimitsPolicy,
18
+ getSudoPolicy,
19
+ getTimeFramePolicy,
20
+ getUniversalActionPolicy,
21
+ getUsageLimitPolicy,
22
+ getValueLimitPolicy,
23
+ } from '@rhinestone/module-sdk';
24
+ import { type SmartAccountClient, createSmartAccountClient, encodeInstallModule } from 'permissionless';
25
+ import { type ToSafeSmartAccountParameters, toSafeSmartAccount } from 'permissionless/accounts';
26
+ import { getAccountNonce } from 'permissionless/actions';
27
+ import { erc7579Actions } from 'permissionless/actions/erc7579';
28
+ import { createPimlicoClient } from 'permissionless/clients/pimlico';
29
+ import {
30
+ http,
31
+ type AbiFunction,
32
+ type Account,
33
+ type Address,
34
+ type Calls,
35
+ type Chain,
36
+ ContractFunctionExecutionError,
37
+ type Hex,
38
+ type Narrow,
39
+ type SignableMessage,
40
+ type WalletClient,
41
+ createPublicClient,
42
+ encodeFunctionData,
43
+ getAbiItem,
44
+ toBytes,
45
+ toFunctionSelector,
46
+ toHex,
47
+ } from 'viem';
48
+ import {
49
+ type UserOperation,
50
+ type WaitForUserOperationReceiptReturnType,
51
+ entryPoint07Address,
52
+ getUserOperationHash,
53
+ } from 'viem/account-abstraction';
54
+ import { privateKeyToAccount } from 'viem/accounts';
55
+ import { bytesToHex } from '../utils/hexBytesAddressUtils.js';
56
+ import {
57
+ daoFactoryAbi,
58
+ mainVotingAbi,
59
+ personalSpaceAdminAbi,
60
+ safe7579Abi,
61
+ safeModuleManagerAbi,
62
+ safeOwnerManagerAbi,
63
+ smartSessionsAbi,
64
+ } from './abis.js';
65
+
66
+ export const DEFAULT_RPC_URL = 'https://rpc-geo-genesis-h0q2s21xx8.t.conduit.xyz';
67
+ export const TESTNET_RPC_URL = 'https://rpc-geo-test-zc16z3tcvf.t.conduit.xyz';
68
+ /**
69
+ * We provide a fallback API key for gas sponsorship for the duration of the
70
+ * Geo Genesis early access period. This API key is gas-limited.
71
+ */
72
+ const DEFAULT_API_KEY = 'pim_KqHm63txxhbCYjdDaWaHqH';
73
+ const BUNDLER_TRANSPORT_URL_BASE = 'https://api.pimlico.io/v2/';
74
+
75
+ const SAFE_7579_MODULE_ADDRESS = '0x7579EE8307284F293B1927136486880611F20002';
76
+ const SAFE_4337_MODULE_ADDRESS = '0x75cf11467937ce3F2f357CE24ffc3DBF8fD5c226';
77
+ const ERC7579_LAUNCHPAD_ADDRESS = '0x7579011aB74c46090561ea277Ba79D510c6C00ff';
78
+
79
+ const SPACE_FACTORY_ADDRESS: Record<string, Hex> = {
80
+ '80451': MAINNET.DAO_FACTORY_ADDRESS,
81
+ '19411': TESTNET.DAO_FACTORY_ADDRESS,
82
+ };
83
+
84
+ const MODULE_TYPE_VALIDATOR = 1;
85
+
86
+ const PUBLIC_SPACE_FUNCTIONS = [
87
+ 'leaveSpace',
88
+ 'leaveSpaceAsEditor',
89
+ 'createProposal',
90
+ 'proposeEdits',
91
+ 'proposeAcceptSubspace',
92
+ 'proposeRemoveSubspace',
93
+ 'proposeAddMember',
94
+ 'proposeRemoveMember',
95
+ 'proposeAddEditor',
96
+ 'proposeRemoveEditor',
97
+ 'cancelProposal',
98
+ 'vote',
99
+ 'execute',
100
+ ];
101
+
102
+ const PERSONAL_SPACE_FUNCTIONS = [
103
+ 'executeProposal',
104
+ 'submitEdits',
105
+ 'submitAcceptSubspace',
106
+ 'submitRemoveSubspace',
107
+ 'submitNewMember',
108
+ 'submitRemoveMember',
109
+ 'leaveSpace',
110
+ 'submitNewEditor',
111
+ 'submitRemoveEditor',
112
+ ];
113
+
114
+ export const GEOGENESIS = {
115
+ id: Number('80451'),
116
+ name: 'Geo Genesis',
117
+ nativeCurrency: {
118
+ name: 'Graph Token',
119
+ symbol: 'GRT',
120
+ decimals: 18,
121
+ },
122
+ rpcUrls: {
123
+ default: {
124
+ http: [DEFAULT_RPC_URL],
125
+ },
126
+ public: {
127
+ http: [DEFAULT_RPC_URL],
128
+ },
129
+ },
130
+ };
131
+
132
+ export const GEO_TESTNET = {
133
+ id: Number('19411'),
134
+ name: 'Geo Testnet',
135
+ nativeCurrency: {
136
+ name: 'Sepolia Ether',
137
+ symbol: 'ETH',
138
+ decimals: 18,
139
+ },
140
+ rpcUrls: {
141
+ default: {
142
+ http: [TESTNET_RPC_URL],
143
+ },
144
+ public: {
145
+ http: [TESTNET_RPC_URL],
146
+ },
147
+ },
148
+ };
149
+
150
+ export type Action = {
151
+ actionTarget: Address;
152
+ actionTargetSelector: Hex;
153
+ actionPolicies: { policy: Address; address: Address; initData: Hex }[];
154
+ };
155
+
156
+ // We re-export these functions to allow creating sessions with policies for
157
+ // additional actions without needing the Rhinestone module SDK.
158
+ export {
159
+ getSudoPolicy,
160
+ getUniversalActionPolicy,
161
+ getSpendingLimitsPolicy,
162
+ getTimeFramePolicy,
163
+ getUsageLimitPolicy,
164
+ getValueLimitPolicy,
165
+ };
166
+
167
+ export type SmartSessionClient = {
168
+ account: Account;
169
+ chain: Chain;
170
+ sendUserOperation: <const calls extends readonly unknown[]>({ calls }: { calls: calls }) => Promise<string>;
171
+ waitForUserOperationReceipt: ({ hash }: { hash: Hex }) => Promise<WaitForUserOperationReceiptReturnType>;
172
+ signMessage: ({ message }: { message: SignableMessage }) => Promise<Hex>;
173
+ };
174
+
175
+ // Gets the legacy Geo smart account wallet client. If the smart account returned
176
+ // by this function is deployed, it means it might need to be updated to have the 7579 module installed
177
+ const getLegacySmartAccountWalletClient = async ({
178
+ owner,
179
+ address,
180
+ chain = GEOGENESIS,
181
+ rpcUrl = DEFAULT_RPC_URL,
182
+ apiKey = DEFAULT_API_KEY,
183
+ }: {
184
+ owner: WalletClient | Account;
185
+ address?: Hex;
186
+ chain?: Chain;
187
+ rpcUrl?: string;
188
+ apiKey?: string;
189
+ }): Promise<SmartAccountClient> => {
190
+ const transport = http(rpcUrl);
191
+ const publicClient = createPublicClient({
192
+ transport,
193
+ chain,
194
+ });
195
+
196
+ const safeAccountParams: ToSafeSmartAccountParameters<'0.7', undefined> = {
197
+ client: publicClient,
198
+ owners: [owner],
199
+ entryPoint: {
200
+ address: entryPoint07Address,
201
+ version: '0.7',
202
+ },
203
+ version: '1.4.1',
204
+ };
205
+ if (address) {
206
+ safeAccountParams.address = address;
207
+ }
208
+
209
+ if (chain.id === GEO_TESTNET.id) {
210
+ // Custom SAFE Addresses
211
+ // TODO: remove this once we have the smart sessions module deployed on testnet
212
+ // (and the canonical addresses are deployed)
213
+ safeAccountParams.safeModuleSetupAddress = '0x2dd68b007B46fBe91B9A7c3EDa5A7a1063cB5b47';
214
+ safeAccountParams.safe4337ModuleAddress = '0x75cf11467937ce3F2f357CE24ffc3DBF8fD5c226';
215
+ safeAccountParams.safeProxyFactoryAddress = '0xd9d2Ba03a7754250FDD71333F444636471CACBC4';
216
+ safeAccountParams.safeSingletonAddress = '0x639245e8476E03e789a244f279b5843b9633b2E7';
217
+ safeAccountParams.multiSendAddress = '0x7B21BBDBdE8D01Df591fdc2dc0bE9956Dde1e16C';
218
+ safeAccountParams.multiSendCallOnlyAddress = '0x32228dDEA8b9A2bd7f2d71A958fF241D79ca5eEC';
219
+ }
220
+ const safeAccount = await toSafeSmartAccount(safeAccountParams);
221
+
222
+ const bundlerTransport = http(`${BUNDLER_TRANSPORT_URL_BASE}${chain.id}/rpc?apikey=${apiKey}`);
223
+ const paymasterClient = createPimlicoClient({
224
+ transport: bundlerTransport,
225
+ chain,
226
+ entryPoint: {
227
+ address: entryPoint07Address,
228
+ version: '0.7',
229
+ },
230
+ });
231
+
232
+ const smartAccountClient = createSmartAccountClient({
233
+ chain,
234
+ account: safeAccount,
235
+ paymaster: paymasterClient,
236
+ bundlerTransport,
237
+ userOperation: {
238
+ estimateFeesPerGas: async () => {
239
+ return (await paymasterClient.getUserOperationGasPrice()).fast;
240
+ },
241
+ },
242
+ });
243
+ return smartAccountClient;
244
+ };
245
+
246
+ // Gets the 7579 smart account wallet client. This is the new type of smart account that
247
+ // includes the session keys validator and the 7579 module.
248
+ const get7579SmartAccountWalletClient = async ({
249
+ owner,
250
+ address,
251
+ chain = GEOGENESIS,
252
+ rpcUrl = DEFAULT_RPC_URL,
253
+ apiKey = DEFAULT_API_KEY,
254
+ }: {
255
+ owner: WalletClient | Account;
256
+ address?: Hex;
257
+ chain?: Chain;
258
+ rpcUrl?: string;
259
+ apiKey?: string;
260
+ }): Promise<SmartAccountClient> => {
261
+ const transport = http(rpcUrl);
262
+ const publicClient = createPublicClient({
263
+ transport,
264
+ chain,
265
+ });
266
+ console.log('owner', owner);
267
+ console.log('chain', chain);
268
+ console.log('rpcUrl', rpcUrl);
269
+ console.log('apiKey', apiKey);
270
+ console.log('address', address);
271
+ const ownerAddress = 'account' in owner ? owner.account?.address : owner.address;
272
+ if (!ownerAddress) {
273
+ throw new Error('Owner address not found');
274
+ }
275
+
276
+ const ownableValidator = getOwnableValidator({
277
+ owners: [ownerAddress],
278
+ threshold: 1,
279
+ });
280
+ const smartSessionsValidator = getSmartSessionsValidator({});
281
+
282
+ const safeAccountParams: ToSafeSmartAccountParameters<'0.7', Hex> = {
283
+ client: publicClient,
284
+ owners: [owner],
285
+ version: '1.4.1' as const,
286
+ entryPoint: {
287
+ address: entryPoint07Address,
288
+ version: '0.7' as const,
289
+ },
290
+ safe4337ModuleAddress: SAFE_7579_MODULE_ADDRESS as Hex,
291
+ erc7579LaunchpadAddress: ERC7579_LAUNCHPAD_ADDRESS as Hex,
292
+ attesters: [
293
+ RHINESTONE_ATTESTER_ADDRESS, // Rhinestone Attester
294
+ ],
295
+ attestersThreshold: 1,
296
+ validators: [
297
+ {
298
+ address: ownableValidator.address,
299
+ context: ownableValidator.initData,
300
+ },
301
+ {
302
+ address: smartSessionsValidator.address,
303
+ context: smartSessionsValidator.initData,
304
+ },
305
+ ],
306
+ };
307
+ if (address) {
308
+ safeAccountParams.address = address;
309
+ }
310
+ const safeAccount = await toSafeSmartAccount(safeAccountParams);
311
+
312
+ const bundlerTransport = http(`${BUNDLER_TRANSPORT_URL_BASE}${chain.id}/rpc?apikey=${apiKey}`);
313
+ const paymasterClient = createPimlicoClient({
314
+ transport: bundlerTransport,
315
+ chain,
316
+ entryPoint: {
317
+ address: entryPoint07Address,
318
+ version: '0.7',
319
+ },
320
+ });
321
+
322
+ const smartAccountClient = createSmartAccountClient({
323
+ chain,
324
+ account: safeAccount,
325
+ paymaster: paymasterClient,
326
+ bundlerTransport,
327
+ userOperation: {
328
+ estimateFeesPerGas: async () => {
329
+ return (await paymasterClient.getUserOperationGasPrice()).fast;
330
+ },
331
+ },
332
+ }).extend(erc7579Actions());
333
+ // For some reason, the .extend() breaks the type inference, so we need to cast to unknown
334
+ return smartAccountClient as unknown as SmartAccountClient;
335
+ };
336
+
337
+ // Checks if the smart account is deployed.
338
+ export const isSmartAccountDeployed = async (smartAccountClient: SmartAccountClient): Promise<boolean> => {
339
+ if (!smartAccountClient.account) {
340
+ throw new Error('Invalid smart account');
341
+ }
342
+ return smartAccountClient.account.isDeployed();
343
+ };
344
+
345
+ export type SmartAccountParams = {
346
+ owner: WalletClient | Account;
347
+ address?: Hex;
348
+ chain?: Chain;
349
+ rpcUrl?: string;
350
+ apiKey?: string;
351
+ };
352
+ // Gets the smart account wallet client. This is the main function to use to get a smart account wallet client.
353
+ // It will return the 7579 smart account wallet client if the smart account is deployed, otherwise it will return the legacy smart account wallet client, that might need to be updated.
354
+ // You can use smartAccountNeedsUpdate to check if the smart account needs to be updated, and then call updateLegacySmartAccount to update it,
355
+ // which requires executing a user operation.
356
+ export const getSmartAccountWalletClient = async ({
357
+ owner,
358
+ address,
359
+ chain = GEOGENESIS,
360
+ rpcUrl = DEFAULT_RPC_URL,
361
+ apiKey = DEFAULT_API_KEY,
362
+ }: SmartAccountParams): Promise<SmartAccountClient> => {
363
+ if (chain.id === GEO_TESTNET.id) {
364
+ // We don't have the smart sessions module deployed on testnet yet, so we need to use the legacy smart account wallet client
365
+ // TODO: remove this once we have the smart sessions module deployed on testnet
366
+ const params: SmartAccountParams = { owner, chain, rpcUrl, apiKey };
367
+ if (address) {
368
+ params.address = address;
369
+ }
370
+ console.log('on testnet, getting legacy smart account wallet client');
371
+ return getLegacySmartAccountWalletClient(params);
372
+ }
373
+ if (address) {
374
+ return get7579SmartAccountWalletClient({ owner, address, chain, rpcUrl, apiKey });
375
+ }
376
+ const legacyClient = await getLegacySmartAccountWalletClient({ owner, chain, rpcUrl, apiKey });
377
+ if (await isSmartAccountDeployed(legacyClient)) {
378
+ return legacyClient;
379
+ }
380
+ return get7579SmartAccountWalletClient({ owner, chain, rpcUrl, apiKey });
381
+ };
382
+
383
+ // Checks if the smart account has the 7579 module installed, the smart sessions validator installed, and the ownable validator installed.
384
+ export const legacySmartAccountUpdateStatus = async (
385
+ smartAccountClient: SmartAccountClient,
386
+ chain: Chain,
387
+ rpcUrl: string,
388
+ ): Promise<{ has7579Module: boolean; hasSmartSessionsValidator: boolean; hasOwnableValidator: boolean }> => {
389
+ if (!smartAccountClient.account) {
390
+ throw new Error('Invalid smart account');
391
+ }
392
+ // We assume the smart account is deployed, so we just need to check if it has the 7579 module and smart sesions validator installed
393
+ // TODO: call the isModuleInstalled function from the safe7579Abi on the
394
+ // smart account, checking if the smart sessions validator is installed. This would fail
395
+ // if the smart account doesn't have the 7579 module installed.
396
+ const transport = http(rpcUrl);
397
+ const publicClient = createPublicClient({
398
+ transport,
399
+ chain,
400
+ });
401
+ const smartSessionsValidator = getSmartSessionsValidator({});
402
+ let isSmartSessionsValidatorInstalled = false;
403
+ try {
404
+ isSmartSessionsValidatorInstalled = (await publicClient.readContract({
405
+ abi: safe7579Abi,
406
+ address: smartAccountClient.account.address,
407
+ functionName: 'isModuleInstalled',
408
+ args: [MODULE_TYPE_VALIDATOR, smartSessionsValidator.address, '0x'],
409
+ })) as boolean;
410
+ } catch (error) {
411
+ if (error instanceof ContractFunctionExecutionError && error.details.includes('execution reverted')) {
412
+ // If the smart account doesn't have the 7579 module installed, the isModuleInstalled function will revert
413
+ return { has7579Module: false, hasSmartSessionsValidator: false, hasOwnableValidator: false };
414
+ }
415
+ throw error;
416
+ }
417
+ const ownableValidator = getOwnableValidator({
418
+ owners: [smartAccountClient.account.address],
419
+ threshold: 1,
420
+ });
421
+ // This shouldn't throw because by now we know the smart account has the 7579 module installed
422
+ const isOwnableValidatorInstalled = (await publicClient.readContract({
423
+ abi: safe7579Abi,
424
+ address: smartAccountClient.account.address,
425
+ functionName: 'isModuleInstalled',
426
+ args: [MODULE_TYPE_VALIDATOR, ownableValidator.address, '0x'],
427
+ })) as boolean;
428
+ return {
429
+ has7579Module: true,
430
+ hasSmartSessionsValidator: isSmartSessionsValidatorInstalled,
431
+ hasOwnableValidator: isOwnableValidatorInstalled,
432
+ };
433
+ };
434
+
435
+ // Checks if the smart account needs to be updated from a legacy ERC-4337 smart account to an ERC-7579 smart account
436
+ // with support for smart sessions.
437
+ export const smartAccountNeedsUpdate = async (
438
+ smartAccountClient: SmartAccountClient,
439
+ chain: Chain,
440
+ rpcUrl: string,
441
+ ): Promise<boolean> => {
442
+ if (chain.id === GEO_TESTNET.id) {
443
+ // We don't have the smart sessions module deployed on testnet yet, so we need to use the legacy smart account wallet client
444
+ // TODO: remove this once we have the smart sessions module deployed on testnet
445
+ return false;
446
+ }
447
+ // If we haven't deployed the smart account, we would always deploy an updated version
448
+ if (!(await isSmartAccountDeployed(smartAccountClient))) {
449
+ return false;
450
+ }
451
+ const updateStatus = await legacySmartAccountUpdateStatus(smartAccountClient, chain, rpcUrl);
452
+ return !updateStatus.has7579Module || !updateStatus.hasSmartSessionsValidator || !updateStatus.hasOwnableValidator;
453
+ };
454
+
455
+ // Legacy Geo smart accounts (i.e. the ones that don't have the 7579 module installed)
456
+ // need to be updated to have the 7579 module installed with the ownable and smart sessions validators.
457
+ export const updateLegacySmartAccount = async (
458
+ smartAccountClient: SmartAccountClient,
459
+ chain: Chain,
460
+ rpcUrl: string,
461
+ ): Promise<WaitForUserOperationReceiptReturnType | undefined> => {
462
+ if (!smartAccountClient.account?.address) {
463
+ throw new Error('Invalid smart account');
464
+ }
465
+ if (chain.id === GEO_TESTNET.id) {
466
+ // We don't have the smart sessions module deployed on testnet yet, so we need to use the legacy smart account wallet client
467
+ // TODO: remove this once we have the smart sessions module deployed on testnet
468
+ console.log('on testnet, skipping updateLegacySmartAccount');
469
+ return;
470
+ }
471
+ const ownableValidator = getOwnableValidator({
472
+ owners: [smartAccountClient.account.address],
473
+ threshold: 1,
474
+ });
475
+ const smartSessionsValidator = getSmartSessionsValidator({});
476
+ const installValidatorsTx = encodeInstallModule({
477
+ account: smartAccountClient.account,
478
+ modules: [
479
+ {
480
+ type: ownableValidator.type,
481
+ address: ownableValidator.address,
482
+ context: ownableValidator.initData,
483
+ },
484
+ {
485
+ type: smartSessionsValidator.type,
486
+ address: smartSessionsValidator.address,
487
+ context: smartSessionsValidator.initData,
488
+ },
489
+ ],
490
+ });
491
+
492
+ const updateStatus = await legacySmartAccountUpdateStatus(smartAccountClient, chain, rpcUrl);
493
+ const calls = [];
494
+ if (!updateStatus.has7579Module) {
495
+ calls.push({
496
+ to: smartAccountClient.account.address,
497
+ data: encodeFunctionData({
498
+ abi: safeModuleManagerAbi,
499
+ functionName: 'enableModule',
500
+ args: [SAFE_7579_MODULE_ADDRESS as Hex],
501
+ }),
502
+ value: BigInt(0),
503
+ });
504
+ calls.push({
505
+ to: smartAccountClient.account.address,
506
+ data: encodeFunctionData({
507
+ abi: safeModuleManagerAbi,
508
+ functionName: 'setFallbackHandler',
509
+ args: [SAFE_7579_MODULE_ADDRESS as Hex],
510
+ }),
511
+ value: BigInt(0),
512
+ });
513
+ calls.push({
514
+ to: smartAccountClient.account.address,
515
+ data: encodeFunctionData({
516
+ abi: safeModuleManagerAbi,
517
+ functionName: 'disableModule',
518
+ args: [SAFE_4337_MODULE_ADDRESS as Hex],
519
+ }),
520
+ value: BigInt(0),
521
+ });
522
+ }
523
+ if (!updateStatus.hasOwnableValidator) {
524
+ calls.push({
525
+ to: installValidatorsTx[0].to,
526
+ data: installValidatorsTx[0].data,
527
+ value: installValidatorsTx[0].value,
528
+ });
529
+ }
530
+ if (!updateStatus.hasSmartSessionsValidator) {
531
+ calls.push({
532
+ to: installValidatorsTx[1].to,
533
+ data: installValidatorsTx[1].data,
534
+ value: installValidatorsTx[1].value,
535
+ });
536
+ }
537
+ if (calls.length === 0) {
538
+ return;
539
+ }
540
+ const tx = await smartAccountClient.sendUserOperation({
541
+ calls,
542
+ });
543
+ const receipt = await smartAccountClient.waitForUserOperationReceipt({
544
+ hash: tx,
545
+ });
546
+ if (!receipt.success) {
547
+ throw new Error('Transaction to update legacy smart account failed');
548
+ }
549
+ return receipt;
550
+ };
551
+
552
+ // Gets the actions that a session key needs permission to perform on a space.
553
+ const getSpaceActions = (space: { address: Hex; type: 'personal' | 'public' }) => {
554
+ const actions: Action[] = [];
555
+ if (space.type === 'public') {
556
+ for (const functionName of PUBLIC_SPACE_FUNCTIONS) {
557
+ actions.push({
558
+ actionTarget: space.address,
559
+ actionTargetSelector: toFunctionSelector(
560
+ getAbiItem({
561
+ abi: mainVotingAbi,
562
+ name: functionName,
563
+ }) as AbiFunction,
564
+ ),
565
+ actionPolicies: [getSudoPolicy()],
566
+ });
567
+ }
568
+ } else {
569
+ for (const functionName of PERSONAL_SPACE_FUNCTIONS) {
570
+ actions.push({
571
+ actionTarget: space.address,
572
+ actionTargetSelector: toFunctionSelector(
573
+ getAbiItem({
574
+ abi: personalSpaceAdminAbi,
575
+ name: functionName,
576
+ }) as AbiFunction,
577
+ ),
578
+ actionPolicies: [getSudoPolicy()],
579
+ });
580
+ }
581
+ }
582
+ return actions;
583
+ };
584
+
585
+ // This is the function that the Connect app uses to create a smart session and
586
+ // enable it on the smart account.
587
+ // It will prompt the user to sign the message to enable the session, and then
588
+ // execute the transaction to enable the session.
589
+ // It will return the permissionId that can be used to create a smart session client.
590
+ export const createSmartSession = async (
591
+ owner: WalletClient,
592
+ accountAddress: Hex,
593
+ sessionPrivateKey: Hex,
594
+ chain: Chain,
595
+ rpcUrl: string,
596
+ {
597
+ allowCreateSpace = false,
598
+ spaces = [],
599
+ additionalActions = [],
600
+ }: {
601
+ allowCreateSpace?: boolean;
602
+ spaces?: {
603
+ address: Hex;
604
+ type: 'personal' | 'public';
605
+ }[];
606
+ additionalActions?: Action[];
607
+ } = {},
608
+ ): Promise<Hex> => {
609
+ const smartAccountClient = await getSmartAccountWalletClient({
610
+ owner,
611
+ address: accountAddress,
612
+ chain,
613
+ rpcUrl,
614
+ });
615
+ if (!smartAccountClient.account) {
616
+ throw new Error('Invalid wallet client');
617
+ }
618
+ if (!smartAccountClient.account.isDeployed()) {
619
+ throw new Error('Smart account must be deployed');
620
+ }
621
+ if (await smartAccountNeedsUpdate(smartAccountClient, chain, rpcUrl)) {
622
+ throw new Error('Smart account needs to be updated');
623
+ }
624
+ if (!smartAccountClient.chain) {
625
+ throw new Error('Invalid smart account chain');
626
+ }
627
+ if (!owner.account) {
628
+ throw new Error('Invalid wallet client');
629
+ }
630
+
631
+ const sessionKeyAccount = privateKeyToAccount(sessionPrivateKey);
632
+ const transport = http(rpcUrl);
633
+ const publicClient = createPublicClient({
634
+ transport,
635
+ chain,
636
+ });
637
+ if (chain.id === GEO_TESTNET.id) {
638
+ // We don't have the smart sessions module deployed on testnet yet, so we need to fake it by adding an account owner
639
+ // TODO: remove this once we have the smart sessions module deployed on testnet
640
+ console.log('on testnet, faking a smart session by adding an account owner');
641
+ const tx = await smartAccountClient.sendUserOperation({
642
+ calls: [
643
+ {
644
+ to: smartAccountClient.account.address,
645
+ data: encodeFunctionData({
646
+ abi: safeOwnerManagerAbi,
647
+ functionName: 'addOwnerWithThreshold',
648
+ args: [sessionKeyAccount.address, BigInt(1)],
649
+ }),
650
+ value: BigInt(0),
651
+ },
652
+ ],
653
+ account: smartAccountClient.account,
654
+ });
655
+ const receipt = await smartAccountClient.waitForUserOperationReceipt({
656
+ hash: tx,
657
+ });
658
+ if (!receipt.success) {
659
+ throw new Error('Transaction to add account owner failed');
660
+ }
661
+ console.log('account owner added');
662
+ return bytesToHex(randomBytes(32)) as Hex;
663
+ }
664
+ // We create a dummy action so that we can execute a userOp immediately and create the session onchain,
665
+ // rather than having to pass along all the enable data to the end user app.
666
+ // In the future, if we enable attestations with the Rhinestone registry, we can remove this and instead
667
+ // call enableSessions on the smart sessions module from the smart account.
668
+ console.log('creating noOpActionPolicy');
669
+ const noOpActionPolicy = getUniversalActionPolicy({
670
+ paramRules: {
671
+ length: BigInt(1),
672
+ // @ts-expect-error - The Rhinestone SDK doesn't export the types we need here
673
+ rules: new Array(16).fill({
674
+ condition: BigInt(0), // ParamCondition.EQUAL
675
+ isLimited: false,
676
+ offset: BigInt(0),
677
+ ref: toHex(toBytes('0x', { size: 32 })),
678
+ usage: { limit: BigInt(0), used: BigInt(0) },
679
+ }),
680
+ },
681
+ valueLimitPerUse: BigInt(0),
682
+ });
683
+ console.log('noOpActionPolicy created');
684
+ const actions: Action[] = [
685
+ {
686
+ actionTarget: sessionKeyAccount.address,
687
+ actionTargetSelector: toFunctionSelector(
688
+ getAbiItem({
689
+ abi: smartSessionsAbi,
690
+ name: 'revokeEnableSignature',
691
+ }) as AbiFunction,
692
+ ),
693
+ actionPolicies: [noOpActionPolicy],
694
+ },
695
+ ];
696
+
697
+ console.log('getting space actions');
698
+ for (const space of spaces) {
699
+ actions.push(...getSpaceActions(space));
700
+ }
701
+ console.log('space actions created');
702
+ if (allowCreateSpace) {
703
+ const spaceFactoryAddress = SPACE_FACTORY_ADDRESS[chain.id.toString()];
704
+ actions.push({
705
+ actionTarget: spaceFactoryAddress,
706
+ actionTargetSelector: toFunctionSelector(
707
+ getAbiItem({
708
+ abi: daoFactoryAbi,
709
+ name: 'createDao',
710
+ }) as AbiFunction,
711
+ ),
712
+ actionPolicies: [getSudoPolicy()],
713
+ });
714
+ }
715
+ if (additionalActions) {
716
+ actions.push(...additionalActions);
717
+ }
718
+ console.log('actions created');
719
+ const session: Session = {
720
+ sessionValidator: OWNABLE_VALIDATOR_ADDRESS,
721
+ sessionValidatorInitData: encodeValidationData({
722
+ threshold: 1,
723
+ owners: [sessionKeyAccount.address],
724
+ }),
725
+ salt: bytesToHex(randomBytes(32)) as Hex,
726
+ userOpPolicies: [getSudoPolicy()],
727
+ erc7739Policies: {
728
+ allowedERC7739Content: [],
729
+ erc1271Policies: [],
730
+ },
731
+ actions,
732
+ chainId: BigInt(smartAccountClient.chain.id),
733
+ permitERC4337Paymaster: true,
734
+ };
735
+ const account = getAccount({
736
+ address: smartAccountClient.account.address,
737
+ type: 'safe',
738
+ });
739
+
740
+ console.log('session object');
741
+ // We use UNSAFE_ENABLE because we're not using Rhinestone's Registry
742
+ // contract to attest to the sessions we're creating.
743
+ // That's also why we set ignoreSecurityAttestations to true.
744
+ const sessionDetails = await getEnableSessionDetails({
745
+ // enableMode: SmartSessionMode.ENABLE,
746
+ sessions: [session],
747
+ account,
748
+ clients: [publicClient],
749
+ // ignoreSecurityAttestations: true,
750
+ });
751
+
752
+ console.log('signing session details');
753
+ // This will prompt the user to sign the message to enable the session
754
+ sessionDetails.enableSessionData.enableSession.permissionEnableSig = await owner.signMessage({
755
+ message: { raw: sessionDetails.permissionEnableHash },
756
+ account: owner.account.address,
757
+ });
758
+ console.log('session details signed');
759
+ const smartSessions = getSmartSessionsValidator({});
760
+ const nonce = await getAccountNonce(publicClient, {
761
+ address: smartAccountClient.account.address,
762
+ entryPointAddress: entryPoint07Address,
763
+ key: encodeValidatorNonce({
764
+ account,
765
+ validator: smartSessions,
766
+ }),
767
+ });
768
+ console.log('nonce');
769
+ // This will be replaced with the actual signature below
770
+ sessionDetails.signature = getOwnableValidatorMockSignature({
771
+ threshold: 1,
772
+ });
773
+ console.log('prep user op');
774
+ const userOperation = await smartAccountClient.prepareUserOperation({
775
+ account: smartAccountClient.account,
776
+ calls: [
777
+ {
778
+ // We use the revokeEnableSignature with permissionId 0 function to create a noop action
779
+ to: sessionKeyAccount.address,
780
+ value: BigInt(0),
781
+ data: encodeFunctionData({
782
+ abi: smartSessionsAbi,
783
+ functionName: 'revokeEnableSignature',
784
+ args: [toHex(toBytes('0x', { size: 32 }))],
785
+ }),
786
+ },
787
+ ],
788
+ nonce,
789
+ signature: encodeSmartSessionSignature(sessionDetails),
790
+ });
791
+ console.log('user operation prepared');
792
+ const userOpHashToSign = getUserOperationHash({
793
+ chainId: chain.id,
794
+ entryPointAddress: entryPoint07Address,
795
+ entryPointVersion: '0.7',
796
+ userOperation,
797
+ });
798
+ console.log('user op hash to sign');
799
+ sessionDetails.signature = await sessionKeyAccount.signMessage({
800
+ message: { raw: userOpHashToSign },
801
+ });
802
+ console.log('user op hash to sign signed');
803
+ userOperation.signature = encodeSmartSessionSignature(sessionDetails);
804
+ console.log('user op hash to sign encoded');
805
+ const userOpHash = await smartAccountClient.sendUserOperation(userOperation as UserOperation); // No idea why the type doesn't match
806
+ console.log('user op hash');
807
+ const receipt = await smartAccountClient.waitForUserOperationReceipt({
808
+ hash: userOpHash,
809
+ });
810
+ if (!receipt.success) {
811
+ throw new Error('Transaction to create smart session failed');
812
+ }
813
+ return getPermissionId({ session });
814
+ };
815
+
816
+ // This is the function that we use on the end user app to create a smart session client that can send transactions to the smart account.
817
+ // The session must have previously been created by the createSmartSession function.
818
+ // The client also includes a signMessage function that can be used to sign messages with the session key.
819
+ export const getSmartSessionClient = async ({
820
+ accountAddress,
821
+ chain = GEOGENESIS,
822
+ rpcUrl = DEFAULT_RPC_URL,
823
+ apiKey = DEFAULT_API_KEY,
824
+ sessionPrivateKey,
825
+ permissionId,
826
+ }: {
827
+ accountAddress: Hex;
828
+ chain?: Chain;
829
+ rpcUrl?: string;
830
+ apiKey?: string;
831
+ sessionPrivateKey: Hex;
832
+ permissionId: Hex;
833
+ }): Promise<SmartSessionClient> => {
834
+ const sessionKeyAccount = privateKeyToAccount(sessionPrivateKey);
835
+ const smartAccountClient = await getSmartAccountWalletClient({
836
+ owner: sessionKeyAccount, // Won't really be used (except in testnet), but we need to pass in an account
837
+ address: accountAddress,
838
+ chain,
839
+ rpcUrl,
840
+ apiKey,
841
+ });
842
+ if (!smartAccountClient.account) {
843
+ throw new Error('Invalid smart account');
844
+ }
845
+
846
+ const smartSessions = getSmartSessionsValidator({});
847
+ const publicClient = createPublicClient({
848
+ transport: http(rpcUrl),
849
+ chain,
850
+ });
851
+
852
+ return {
853
+ account: smartAccountClient.account,
854
+ chain,
855
+ sendUserOperation: async <const calls extends readonly unknown[]>({ calls }: { calls: calls }) => {
856
+ if (!smartAccountClient.account) {
857
+ throw new Error('Invalid smart account');
858
+ }
859
+ if (chain.id === GEO_TESTNET.id) {
860
+ // We don't have the smart sessions module deployed on testnet yet, so we need to use the legacy smart account wallet client
861
+ // TODO: remove this once we have the smart sessions module deployed on testnet
862
+ return smartAccountClient.sendUserOperation({
863
+ calls: calls as Calls<Narrow<calls>>,
864
+ account: smartAccountClient.account,
865
+ });
866
+ }
867
+ const account = getAccount({
868
+ address: smartAccountClient.account.address,
869
+ type: 'safe',
870
+ });
871
+ const sessionDetails = {
872
+ mode: SmartSessionMode.USE,
873
+ permissionId,
874
+ signature: getOwnableValidatorMockSignature({
875
+ threshold: 1,
876
+ }),
877
+ };
878
+ const nonce = await getAccountNonce(publicClient, {
879
+ address: smartAccountClient.account.address,
880
+ entryPointAddress: entryPoint07Address,
881
+ key: encodeValidatorNonce({
882
+ account,
883
+ validator: smartSessions,
884
+ }),
885
+ });
886
+ const userOperation = await smartAccountClient.prepareUserOperation({
887
+ account: smartAccountClient.account,
888
+ calls,
889
+ nonce,
890
+ signature: encodeSmartSessionSignature(sessionDetails),
891
+ });
892
+
893
+ const userOpHashToSign = getUserOperationHash({
894
+ chainId: chain.id,
895
+ entryPointAddress: entryPoint07Address,
896
+ entryPointVersion: '0.7',
897
+ userOperation,
898
+ });
899
+
900
+ sessionDetails.signature = await sessionKeyAccount.signMessage({
901
+ message: { raw: userOpHashToSign },
902
+ });
903
+
904
+ userOperation.signature = encodeSmartSessionSignature(sessionDetails);
905
+
906
+ return smartAccountClient.sendUserOperation(userOperation as UserOperation);
907
+ },
908
+ signMessage: async ({ message }: { message: SignableMessage }) => {
909
+ return sessionKeyAccount.signMessage({ message });
910
+ },
911
+ waitForUserOperationReceipt: async ({ hash }: { hash: Hex }) => {
912
+ return smartAccountClient.waitForUserOperationReceipt({ hash });
913
+ },
914
+ };
915
+ };