@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.
- package/dist/connect/abis/MainVotingPlugin.json +1865 -0
- package/dist/connect/abis/PersonalSpaceAdminPlugin.json +531 -0
- package/dist/connect/abis.d.ts +115 -0
- package/dist/connect/abis.d.ts.map +1 -0
- package/dist/connect/abis.js +141 -0
- package/dist/connect/abis.js.map +1 -0
- package/dist/connect/auth-storage.d.ts +15 -0
- package/dist/connect/auth-storage.js +53 -0
- package/dist/connect/auth-storage.js.map +1 -0
- package/dist/connect/create-app-identity.d.ts +7 -0
- package/dist/connect/create-app-identity.js +15 -0
- package/dist/connect/create-app-identity.js.map +1 -0
- package/dist/connect/create-auth-url.d.ts +15 -0
- package/dist/connect/create-callback-params.d.ts +28 -0
- package/dist/connect/create-callback-params.d.ts.map +1 -1
- package/dist/connect/create-callback-params.js.map +1 -1
- package/dist/connect/create-identity-keys.d.ts +3 -0
- package/dist/connect/create-identity-keys.js +20 -0
- package/dist/connect/create-identity-keys.js.map +1 -0
- package/dist/connect/identity-encryption.d.ts +12 -0
- package/dist/connect/identity-encryption.d.ts.map +1 -1
- package/dist/connect/identity-encryption.js +187 -0
- package/dist/connect/identity-encryption.js.map +1 -0
- package/dist/connect/index.d.ts +11 -0
- package/dist/connect/index.d.ts.map +1 -1
- package/dist/connect/index.js +11 -0
- package/dist/connect/index.js.map +1 -0
- package/dist/connect/login.d.ts +22 -0
- package/dist/connect/login.d.ts.map +1 -1
- package/dist/connect/login.js +172 -0
- package/dist/connect/login.js.map +1 -0
- package/dist/connect/parse-auth-params.d.ts +14 -0
- package/dist/connect/parse-auth-params.d.ts.map +1 -0
- package/dist/connect/parse-auth-params.js +40 -0
- package/dist/connect/parse-auth-params.js.map +1 -0
- package/dist/connect/parse-callback-params.d.ts +13 -0
- package/dist/connect/parse-callback-params.d.ts.map +1 -1
- package/dist/connect/parse-callback-params.js +4 -1
- package/dist/connect/parse-callback-params.js.map +1 -1
- package/dist/connect/smart-account.d.ts +96 -0
- package/dist/connect/smart-account.d.ts.map +1 -0
- package/dist/connect/smart-account.js +761 -0
- package/dist/connect/smart-account.js.map +1 -0
- package/dist/connect/types.d.ts +2 -0
- package/dist/connect/types.d.ts.map +1 -1
- package/dist/connect/types.js.map +1 -1
- package/dist/entity/create.d.ts +8 -0
- package/dist/entity/create.js +51 -0
- package/dist/entity/create.js.map +1 -0
- package/dist/entity/decodedEntitiesCache.d.ts +23 -0
- package/dist/entity/decodedEntitiesCache.d.ts.map +1 -1
- package/dist/entity/decodedEntitiesCache.js +2 -0
- package/dist/entity/decodedEntitiesCache.js.map +1 -0
- package/dist/entity/delete.d.ts +12 -0
- package/dist/entity/delete.js +44 -0
- package/dist/entity/delete.js.map +1 -0
- package/dist/entity/entity.d.ts +18 -0
- package/dist/entity/entity.js +19 -0
- package/dist/entity/entity.js.map +1 -0
- package/dist/entity/entityRelationParentsMap.d.ts +4 -0
- package/dist/entity/entityRelationParentsMap.js +2 -0
- package/dist/entity/entityRelationParentsMap.js.map +1 -0
- package/dist/entity/findMany.d.ts +22 -0
- package/dist/entity/findMany.d.ts.map +1 -1
- package/dist/entity/findMany.js +8 -8
- package/dist/entity/findMany.js.map +1 -1
- package/dist/entity/findOne.d.ts +8 -0
- package/dist/entity/findOne.js +31 -0
- package/dist/entity/findOne.js.map +1 -0
- package/dist/entity/getEntityRelations.d.ts +4 -0
- package/dist/entity/getEntityRelations.d.ts.map +1 -1
- package/dist/entity/getEntityRelations.js +35 -0
- package/dist/entity/getEntityRelations.js.map +1 -0
- package/dist/entity/hasValidTypesProperty.d.ts +2 -0
- package/dist/entity/hasValidTypesProperty.d.ts.map +1 -0
- package/dist/entity/hasValidTypesProperty.js +4 -0
- package/dist/entity/hasValidTypesProperty.js.map +1 -0
- package/dist/entity/index.d.ts +9 -0
- package/dist/entity/index.js +9 -0
- package/dist/entity/index.js.map +1 -0
- package/dist/entity/relationParentsMap.d.ts +4 -0
- package/dist/entity/relationParentsMap.js +2 -0
- package/dist/entity/relationParentsMap.js.map +1 -0
- package/dist/entity/removeRelation.d.ts +7 -0
- package/dist/entity/removeRelation.js +17 -0
- package/dist/entity/removeRelation.js.map +1 -0
- package/dist/entity/test.d.ts +2 -0
- package/dist/entity/test.d.ts.map +1 -0
- package/dist/entity/test.js +2 -0
- package/dist/entity/test.js.map +1 -0
- package/dist/entity/types.d.ts +8 -8
- package/dist/entity/update.d.ts +8 -0
- package/dist/entity/update.js +58 -0
- package/dist/entity/update.js.map +1 -0
- package/dist/entity/variant-schema.d.ts +247 -0
- package/dist/entity/variant-schema.d.ts.map +1 -0
- package/dist/entity/variant-schema.js +204 -0
- package/dist/entity/variant-schema.js.map +1 -0
- package/dist/identity/auth-storage.d.ts +6 -0
- package/dist/identity/auth-storage.d.ts.map +1 -1
- package/dist/identity/auth-storage.js +52 -0
- package/dist/identity/auth-storage.js.map +1 -0
- package/dist/identity/get-verified-identity.d.ts +7 -0
- package/dist/identity/get-verified-identity.d.ts.map +1 -1
- package/dist/identity/get-verified-identity.js +37 -0
- package/dist/identity/get-verified-identity.js.map +1 -0
- package/dist/identity/identity-encryption.d.ts +7 -0
- package/dist/identity/identity-encryption.js +120 -0
- package/dist/identity/identity-encryption.js.map +1 -0
- package/dist/identity/index.d.ts +7 -0
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +7 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/logout.d.ts +3 -0
- package/dist/identity/logout.js +9 -0
- package/dist/identity/logout.js.map +1 -0
- package/dist/identity/prove-ownership.d.ts +15 -0
- package/dist/identity/prove-ownership.d.ts.map +1 -1
- package/dist/identity/prove-ownership.js +90 -0
- package/dist/identity/prove-ownership.js.map +1 -0
- package/dist/identity/types.d.ts +37 -0
- package/dist/identity/types.d.ts.map +1 -0
- package/dist/identity/types.js +11 -0
- package/dist/identity/types.js.map +1 -0
- package/dist/inboxes/create-inbox.d.ts +22 -0
- package/dist/inboxes/create-inbox.js +76 -0
- package/dist/inboxes/create-inbox.js.map +1 -0
- package/dist/inboxes/get-list-inboxes.d.ts +20 -0
- package/dist/inboxes/get-list-inboxes.js +45 -0
- package/dist/inboxes/get-list-inboxes.js.map +1 -0
- package/dist/inboxes/index.d.ts +11 -0
- package/dist/inboxes/index.js +11 -0
- package/dist/inboxes/index.js.map +1 -0
- package/dist/inboxes/merge-messages.d.ts +6 -0
- package/dist/inboxes/merge-messages.js +23 -0
- package/dist/inboxes/merge-messages.js.map +1 -0
- package/dist/inboxes/message-encryption.d.ts +15 -0
- package/dist/inboxes/message-encryption.js +29 -0
- package/dist/inboxes/message-encryption.js.map +1 -0
- package/dist/inboxes/message-validation.d.ts +6 -0
- package/dist/inboxes/message-validation.d.ts.map +1 -1
- package/dist/inboxes/message-validation.js +53 -0
- package/dist/inboxes/message-validation.js.map +1 -0
- package/dist/inboxes/prepare-message.d.ts +2 -2
- package/dist/inboxes/prepare-message.js +78 -0
- package/dist/inboxes/prepare-message.js.map +1 -0
- package/dist/inboxes/recover-inbox-creator.d.ts +5 -0
- package/dist/inboxes/recover-inbox-creator.js +24 -0
- package/dist/inboxes/recover-inbox-creator.js.map +1 -0
- package/dist/inboxes/recover-inbox-message-signer.d.ts +4 -0
- package/dist/inboxes/recover-inbox-message-signer.js +32 -0
- package/dist/inboxes/recover-inbox-message-signer.js.map +1 -0
- package/dist/inboxes/send-message.d.ts +19 -0
- package/dist/inboxes/send-message.js +58 -0
- package/dist/inboxes/send-message.js.map +1 -0
- package/dist/inboxes/types.d.ts +4 -0
- package/dist/inboxes/types.d.ts.map +1 -0
- package/dist/inboxes/types.js +3 -0
- package/dist/inboxes/types.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/key/create-key.d.ts +11 -0
- package/dist/key/create-key.d.ts.map +1 -0
- package/dist/key/create-key.js +22 -0
- package/dist/key/create-key.js.map +1 -0
- package/dist/key/decrypt-key.d.ts +9 -0
- package/dist/key/decrypt-key.d.ts.map +1 -0
- package/dist/key/decrypt-key.js +16 -0
- package/dist/key/decrypt-key.js.map +1 -0
- package/dist/key/encrypt-key.d.ts +11 -0
- package/dist/key/encrypt-key.d.ts.map +1 -0
- package/dist/key/encrypt-key.js +20 -0
- package/dist/key/encrypt-key.js.map +1 -0
- package/dist/key/index.d.ts +5 -0
- package/dist/key/index.d.ts.map +1 -0
- package/dist/key/index.js +5 -0
- package/dist/key/index.js.map +1 -0
- package/dist/key/key-box.d.ts +19 -0
- package/dist/key/key-box.d.ts.map +1 -0
- package/dist/key/key-box.js +38 -0
- package/dist/key/key-box.js.map +1 -0
- package/dist/messages/decrypt-message.d.ts +7 -0
- package/dist/messages/decrypt-message.d.ts.map +1 -0
- package/dist/messages/decrypt-message.js +11 -0
- package/dist/messages/decrypt-message.js.map +1 -0
- package/dist/messages/encrypt-message.d.ts +7 -0
- package/dist/messages/encrypt-message.d.ts.map +1 -0
- package/dist/messages/encrypt-message.js +12 -0
- package/dist/messages/encrypt-message.js.map +1 -0
- package/dist/messages/index.d.ts +6 -0
- package/dist/messages/index.js +6 -0
- package/dist/messages/index.js.map +1 -0
- package/dist/messages/serialize.d.ts +3 -0
- package/dist/messages/serialize.d.ts.map +1 -0
- package/dist/messages/serialize.js +30 -0
- package/dist/messages/serialize.js.map +1 -0
- package/dist/messages/signed-update-message.d.ts +23 -0
- package/dist/messages/signed-update-message.js +56 -0
- package/dist/messages/signed-update-message.js.map +1 -0
- package/dist/messages/types.d.ts +1268 -0
- package/dist/messages/types.d.ts.map +1 -1
- package/dist/messages/types.js +312 -0
- package/dist/messages/types.js.map +1 -0
- package/dist/space-events/accept-invitation.d.ts +9 -0
- package/dist/space-events/accept-invitation.js +28 -0
- package/dist/space-events/accept-invitation.js.map +1 -0
- package/dist/space-events/apply-event.d.ts +11 -0
- package/dist/space-events/apply-event.js +130 -0
- package/dist/space-events/apply-event.js.map +1 -0
- package/dist/space-events/create-inbox.d.ts +14 -0
- package/dist/space-events/create-inbox.js +41 -0
- package/dist/space-events/create-inbox.js.map +1 -0
- package/dist/space-events/create-invitation.d.ts +12 -0
- package/dist/space-events/create-invitation.js +30 -0
- package/dist/space-events/create-invitation.js.map +1 -0
- package/dist/space-events/create-space.d.ts +9 -0
- package/dist/space-events/create-space.js +29 -0
- package/dist/space-events/create-space.js.map +1 -0
- package/dist/space-events/delete-space.d.ts +10 -0
- package/dist/space-events/delete-space.js +30 -0
- package/dist/space-events/delete-space.js.map +1 -0
- package/dist/space-events/hash-event.d.ts +3 -0
- package/dist/space-events/hash-event.js +7 -0
- package/dist/space-events/hash-event.js.map +1 -0
- package/dist/space-events/index.d.ts +9 -0
- package/dist/space-events/index.js +9 -0
- package/dist/space-events/index.js.map +1 -0
- package/dist/space-events/types.d.ts +222 -0
- package/dist/space-events/types.d.ts.map +1 -0
- package/dist/space-events/types.js +102 -0
- package/dist/space-events/types.js.map +1 -0
- package/dist/space-info/decrypt-space-info.d.ts +7 -0
- package/dist/space-info/decrypt-space-info.js +18 -0
- package/dist/space-info/decrypt-space-info.js.map +1 -0
- package/dist/space-info/encrypt-and-sign-space-info.d.ts +17 -0
- package/dist/space-info/encrypt-and-sign-space-info.js +39 -0
- package/dist/space-info/encrypt-and-sign-space-info.js.map +1 -0
- package/dist/space-info/index.d.ts +4 -0
- package/dist/space-info/index.js +4 -0
- package/dist/space-info/index.js.map +1 -0
- package/dist/space-info/types.d.ts +6 -0
- package/dist/space-info/types.d.ts.map +1 -0
- package/dist/space-info/types.js +5 -0
- package/dist/space-info/types.js.map +1 -0
- package/dist/store-connect.d.ts +149 -0
- package/dist/store-connect.d.ts.map +1 -1
- package/dist/store-connect.js +289 -0
- package/dist/store-connect.js.map +1 -0
- package/dist/store.d.ts +158 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +354 -0
- package/dist/store.js.map +1 -0
- package/dist/type/type.d.ts +14 -0
- package/dist/type/type.d.ts.map +1 -1
- package/dist/type/type.js +25 -0
- package/dist/type/type.js.map +1 -0
- package/dist/types.d.ts +80 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +37 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/assertExhaustive.d.ts +2 -0
- package/dist/utils/assertExhaustive.d.ts.map +1 -0
- package/dist/utils/assertExhaustive.js +4 -0
- package/dist/utils/assertExhaustive.js.map +1 -0
- package/dist/utils/automergeId.d.ts +1 -1
- package/dist/utils/automergeId.d.ts.map +1 -1
- package/dist/utils/automergeId.js +1 -1
- package/dist/utils/automergeId.js.map +1 -1
- package/dist/utils/base58.d.ts +36 -0
- package/dist/utils/base58.d.ts.map +1 -0
- package/dist/utils/base58.js +62 -0
- package/dist/utils/base58.js.map +1 -0
- package/dist/utils/hexBytesAddressUtils.d.ts +4 -0
- package/dist/utils/hexBytesAddressUtils.d.ts.map +1 -0
- package/dist/utils/hexBytesAddressUtils.js +21 -0
- package/dist/utils/hexBytesAddressUtils.js.map +1 -0
- package/dist/utils/index.d.ts +9 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/internal/base58Utils.d.ts +4 -0
- package/dist/utils/internal/base58Utils.d.ts.map +1 -0
- package/dist/utils/internal/base58Utils.js +40 -0
- package/dist/utils/internal/base58Utils.js.map +1 -0
- package/dist/utils/internal/deep-merge.d.ts +7 -0
- package/dist/utils/internal/deep-merge.d.ts.map +1 -0
- package/dist/utils/internal/deep-merge.js +33 -0
- package/dist/utils/internal/deep-merge.js.map +1 -0
- package/dist/utils/isRelationField.d.ts +3 -0
- package/dist/utils/isRelationField.d.ts.map +1 -0
- package/dist/utils/isRelationField.js +8 -0
- package/dist/utils/isRelationField.js.map +1 -0
- package/dist/utils/jsc.d.ts +49 -0
- package/dist/utils/jsc.d.ts.map +1 -0
- package/dist/utils/jsc.js +88 -0
- package/dist/utils/jsc.js.map +1 -0
- package/dist/utils/stringToUint8Array.d.ts +3 -0
- package/dist/utils/stringToUint8Array.d.ts.map +1 -0
- package/dist/utils/stringToUint8Array.js +9 -0
- package/dist/utils/stringToUint8Array.js.map +1 -0
- package/package.json +5 -2
- package/src/connect/abis/MainVotingPlugin.json +1865 -0
- package/src/connect/abis/PersonalSpaceAdminPlugin.json +531 -0
- package/src/connect/abis.ts +183 -0
- package/src/connect/create-callback-params.ts +4 -1
- package/src/connect/identity-encryption.ts +10 -14
- package/src/connect/index.ts +1 -1
- package/src/connect/login.ts +106 -18
- package/src/connect/parse-callback-params.ts +4 -1
- package/src/connect/smart-account.ts +915 -0
- package/src/connect/types.ts +2 -0
- package/src/entity/decodedEntitiesCache.ts +1 -1
- package/src/entity/findMany.ts +16 -14
- package/src/entity/getEntityRelations.ts +1 -1
- package/src/entity/types.ts +8 -8
- package/src/identity/auth-storage.ts +11 -1
- package/src/identity/get-verified-identity.ts +6 -1
- package/src/identity/index.ts +1 -1
- package/src/identity/prove-ownership.ts +52 -8
- package/src/inboxes/message-validation.ts +17 -2
- package/src/messages/types.ts +6 -0
- package/src/store-connect.ts +1 -52
- package/src/store.ts +78 -48
- package/src/type/type.ts +4 -2
- package/src/types.ts +19 -1
- package/src/utils/automergeId.ts +1 -1
- package/dist/connect/prove-ownership.d.ts.map +0 -1
- 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
|
+
};
|