@account-kit/wallet-client 0.1.0-alpha.4 → 0.1.0-alpha.5

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 (141) hide show
  1. package/dist/esm/capabilities/eip7702Auth.d.ts +4 -0
  2. package/dist/esm/capabilities/eip7702Auth.js +16 -0
  3. package/dist/esm/capabilities/eip7702Auth.js.map +1 -0
  4. package/dist/esm/capabilities/index.d.ts +4 -0
  5. package/dist/esm/capabilities/index.js +2 -0
  6. package/dist/esm/capabilities/index.js.map +1 -1
  7. package/dist/esm/capabilities/permissions/index.d.ts +1 -1
  8. package/dist/esm/capabilities/permissions/mav2.js +1 -0
  9. package/dist/esm/capabilities/permissions/mav2.js.map +1 -1
  10. package/dist/esm/client/actions/getCallsStatus.d.ts +1 -2
  11. package/dist/esm/client/actions/getCallsStatus.js +19 -0
  12. package/dist/esm/client/actions/getCallsStatus.js.map +1 -1
  13. package/dist/esm/client/actions/grantPermissions.d.ts +6 -6
  14. package/dist/esm/client/actions/grantPermissions.js +115 -3
  15. package/dist/esm/client/actions/grantPermissions.js.map +1 -1
  16. package/dist/esm/client/actions/prepareCalls.d.ts +4 -4
  17. package/dist/esm/client/actions/prepareCalls.js +38 -5
  18. package/dist/esm/client/actions/prepareCalls.js.map +1 -1
  19. package/dist/esm/client/actions/requestAccount.d.ts +3 -4
  20. package/dist/esm/client/actions/requestAccount.js +18 -1
  21. package/dist/esm/client/actions/requestAccount.js.map +1 -1
  22. package/dist/esm/client/actions/signMessage.d.ts +3 -3
  23. package/dist/esm/client/actions/signMessage.js +18 -0
  24. package/dist/esm/client/actions/signMessage.js.map +1 -1
  25. package/dist/esm/client/actions/signSignatureRequest.d.ts +3 -3
  26. package/dist/esm/client/actions/signSignatureRequest.js +2 -2
  27. package/dist/esm/client/actions/signSignatureRequest.js.map +1 -1
  28. package/dist/esm/client/actions/signTypedData.d.ts +2 -2
  29. package/dist/esm/client/actions/signTypedData.js +31 -0
  30. package/dist/esm/client/actions/signTypedData.js.map +1 -1
  31. package/dist/esm/client/client.e2e-test.js +19 -19
  32. package/dist/esm/client/client.e2e-test.js.map +1 -1
  33. package/dist/esm/client/decorator.d.ts +4 -4
  34. package/dist/esm/client/decorator.js.map +1 -1
  35. package/dist/esm/client/index.d.ts +35 -10
  36. package/dist/esm/client/index.js +0 -29
  37. package/dist/esm/client/index.js.map +1 -1
  38. package/dist/esm/isomorphic/actions/createSession.js +21 -10
  39. package/dist/esm/isomorphic/actions/createSession.js.map +1 -1
  40. package/dist/esm/isomorphic/actions/getCallsStatus.js +62 -9
  41. package/dist/esm/isomorphic/actions/getCallsStatus.js.map +1 -1
  42. package/dist/esm/isomorphic/actions/prepareCalls.js +18 -11
  43. package/dist/esm/isomorphic/actions/prepareCalls.js.map +1 -1
  44. package/dist/esm/isomorphic/actions/sendPreparedCalls.js +2 -2
  45. package/dist/esm/isomorphic/actions/sendPreparedCalls.js.map +1 -1
  46. package/dist/esm/isomorphic/client.d.ts +1 -1
  47. package/dist/esm/isomorphic/utils/7702.d.ts +9 -3
  48. package/dist/esm/isomorphic/utils/7702.js +35 -8
  49. package/dist/esm/isomorphic/utils/7702.js.map +1 -1
  50. package/dist/esm/isomorphic/utils/createAccount.d.ts +2 -2
  51. package/dist/esm/isomorphic/utils/createAccount.js +4 -3
  52. package/dist/esm/isomorphic/utils/createAccount.js.map +1 -1
  53. package/dist/esm/isomorphic/utils/parsePermissionsContext.d.ts +2 -2
  54. package/dist/esm/isomorphic/utils/parsePermissionsContext.js +8 -7
  55. package/dist/esm/isomorphic/utils/parsePermissionsContext.js.map +1 -1
  56. package/dist/esm/local/client.d.ts +2 -2
  57. package/dist/esm/local/client.js.map +1 -1
  58. package/dist/esm/remote/client.d.ts +8 -2
  59. package/dist/esm/remote/client.js +1 -7
  60. package/dist/esm/remote/client.js.map +1 -1
  61. package/dist/esm/rpc/request.d.ts +12 -2
  62. package/dist/esm/rpc/request.js +6 -9
  63. package/dist/esm/rpc/request.js.map +1 -1
  64. package/dist/esm/rpc/schema.d.ts +23 -13
  65. package/dist/esm/schemas.d.ts +3 -1
  66. package/dist/esm/schemas.js +6 -4
  67. package/dist/esm/schemas.js.map +1 -1
  68. package/dist/esm/types.d.ts +7 -10
  69. package/dist/esm/types.js.map +1 -1
  70. package/dist/types/capabilities/eip7702Auth.d.ts +5 -0
  71. package/dist/types/capabilities/eip7702Auth.d.ts.map +1 -0
  72. package/dist/types/capabilities/index.d.ts +4 -0
  73. package/dist/types/capabilities/index.d.ts.map +1 -1
  74. package/dist/types/capabilities/permissions/index.d.ts +1 -1
  75. package/dist/types/capabilities/permissions/mav2.d.ts.map +1 -1
  76. package/dist/types/client/actions/getCallsStatus.d.ts +1 -2
  77. package/dist/types/client/actions/getCallsStatus.d.ts.map +1 -1
  78. package/dist/types/client/actions/grantPermissions.d.ts +6 -6
  79. package/dist/types/client/actions/grantPermissions.d.ts.map +1 -1
  80. package/dist/types/client/actions/prepareCalls.d.ts +4 -4
  81. package/dist/types/client/actions/prepareCalls.d.ts.map +1 -1
  82. package/dist/types/client/actions/requestAccount.d.ts +3 -4
  83. package/dist/types/client/actions/requestAccount.d.ts.map +1 -1
  84. package/dist/types/client/actions/signMessage.d.ts +3 -3
  85. package/dist/types/client/actions/signMessage.d.ts.map +1 -1
  86. package/dist/types/client/actions/signSignatureRequest.d.ts +3 -3
  87. package/dist/types/client/actions/signSignatureRequest.d.ts.map +1 -1
  88. package/dist/types/client/actions/signTypedData.d.ts +2 -2
  89. package/dist/types/client/actions/signTypedData.d.ts.map +1 -1
  90. package/dist/types/client/decorator.d.ts +4 -4
  91. package/dist/types/client/decorator.d.ts.map +1 -1
  92. package/dist/types/client/index.d.ts +35 -10
  93. package/dist/types/client/index.d.ts.map +1 -1
  94. package/dist/types/isomorphic/actions/createSession.d.ts.map +1 -1
  95. package/dist/types/isomorphic/actions/getCallsStatus.d.ts.map +1 -1
  96. package/dist/types/isomorphic/actions/prepareCalls.d.ts.map +1 -1
  97. package/dist/types/isomorphic/client.d.ts +1 -1
  98. package/dist/types/isomorphic/utils/7702.d.ts +9 -3
  99. package/dist/types/isomorphic/utils/7702.d.ts.map +1 -1
  100. package/dist/types/isomorphic/utils/createAccount.d.ts +2 -2
  101. package/dist/types/isomorphic/utils/createAccount.d.ts.map +1 -1
  102. package/dist/types/isomorphic/utils/parsePermissionsContext.d.ts +2 -2
  103. package/dist/types/isomorphic/utils/parsePermissionsContext.d.ts.map +1 -1
  104. package/dist/types/local/client.d.ts +2 -2
  105. package/dist/types/local/client.d.ts.map +1 -1
  106. package/dist/types/remote/client.d.ts +8 -2
  107. package/dist/types/remote/client.d.ts.map +1 -1
  108. package/dist/types/rpc/request.d.ts +12 -2
  109. package/dist/types/rpc/request.d.ts.map +1 -1
  110. package/dist/types/rpc/schema.d.ts +23 -13
  111. package/dist/types/rpc/schema.d.ts.map +1 -1
  112. package/dist/types/schemas.d.ts +3 -1
  113. package/dist/types/schemas.d.ts.map +1 -1
  114. package/dist/types/types.d.ts +7 -10
  115. package/dist/types/types.d.ts.map +1 -1
  116. package/package.json +2 -2
  117. package/src/capabilities/eip7702Auth.ts +19 -0
  118. package/src/capabilities/index.ts +2 -0
  119. package/src/capabilities/permissions/mav2.ts +1 -0
  120. package/src/client/actions/getCallsStatus.ts +0 -10
  121. package/src/client/actions/grantPermissions.ts +12 -25
  122. package/src/client/actions/prepareCalls.ts +18 -23
  123. package/src/client/actions/requestAccount.ts +9 -26
  124. package/src/client/actions/signMessage.ts +2 -17
  125. package/src/client/actions/signSignatureRequest.ts +5 -5
  126. package/src/client/actions/signTypedData.ts +1 -16
  127. package/src/client/client.e2e-test.ts +22 -22
  128. package/src/client/decorator.ts +5 -10
  129. package/src/client/index.ts +16 -39
  130. package/src/isomorphic/actions/createSession.ts +29 -10
  131. package/src/isomorphic/actions/getCallsStatus.ts +82 -10
  132. package/src/isomorphic/actions/prepareCalls.ts +19 -11
  133. package/src/isomorphic/actions/sendPreparedCalls.ts +2 -2
  134. package/src/isomorphic/utils/7702.ts +61 -13
  135. package/src/isomorphic/utils/createAccount.ts +5 -5
  136. package/src/isomorphic/utils/parsePermissionsContext.ts +9 -9
  137. package/src/local/client.ts +3 -5
  138. package/src/remote/client.ts +5 -13
  139. package/src/rpc/request.ts +8 -9
  140. package/src/schemas.ts +8 -4
  141. package/src/types.ts +5 -21
@@ -1,12 +1,6 @@
1
1
  import type { SmartAccountSigner } from "@aa-sdk/core";
2
2
  import type { AlchemyTransport } from "@account-kit/infra";
3
- import type {
4
- Address,
5
- Chain,
6
- IsUndefined,
7
- JsonRpcAccount,
8
- Prettify,
9
- } from "viem";
3
+ import type { Address, Chain, Prettify } from "viem";
10
4
  import { createLocalClient } from "../local/client.js";
11
5
  import { createRemoteClient } from "../remote/client.js";
12
6
  import type { InnerWalletApiClient } from "../types.ts";
@@ -16,40 +10,19 @@ import {
16
10
  } from "./decorator.js";
17
11
 
18
12
  export type SmartWalletClientParams<
19
- TAccount extends JsonRpcAccount<Address> | undefined =
20
- | JsonRpcAccount<Address>
21
- | undefined,
22
- > = Prettify<
23
- {
24
- transport: AlchemyTransport;
25
- chain: Chain;
26
- signer: SmartAccountSigner;
27
- mode: "local" | "remote";
28
- policyId?: string;
29
- } & (IsUndefined<TAccount> extends true
30
- ? {
31
- account?: never;
32
- }
33
- : {
34
- account: Address;
35
- })
36
- >;
13
+ TAccount extends Address | undefined = Address | undefined,
14
+ > = Prettify<{
15
+ transport: AlchemyTransport;
16
+ chain: Chain;
17
+ signer: SmartAccountSigner;
18
+ mode: "local" | "remote";
19
+ policyId?: string;
20
+ account?: TAccount | Address | undefined;
21
+ }>;
37
22
 
38
23
  export type SmartWalletClient<
39
- TAccount extends JsonRpcAccount<Address> | undefined =
40
- | JsonRpcAccount<Address>
41
- | undefined,
42
- > = InnerWalletApiClient<TAccount> & SmartWalletActions<TAccount>;
43
-
44
- export function createSmartWalletClient<
45
- TAccount extends JsonRpcAccount<Address> | undefined =
46
- | JsonRpcAccount<Address>
47
- | undefined,
48
- >(params: SmartWalletClientParams<TAccount>): SmartWalletClient<TAccount>;
49
-
50
- export function createSmartWalletClient<
51
- TAccount extends JsonRpcAccount<Address> = JsonRpcAccount<Address>,
52
- >(params: SmartWalletClientParams<TAccount>): SmartWalletClient<TAccount>;
24
+ TAccount extends Address | undefined = Address | undefined,
25
+ > = InnerWalletApiClient & SmartWalletActions<TAccount>;
53
26
 
54
27
  /**
55
28
  * Creates a smart wallet client that can be used to interact with a smart account.
@@ -80,6 +53,10 @@ export function createSmartWalletClient<
80
53
  * signer,
81
54
  * });
82
55
  */
56
+ export function createSmartWalletClient<
57
+ TAccount extends Address | undefined = undefined,
58
+ >(params: SmartWalletClientParams<TAccount>): SmartWalletClient<TAccount>;
59
+
83
60
  export function createSmartWalletClient(
84
61
  params: SmartWalletClientParams,
85
62
  ): SmartWalletClient {
@@ -26,6 +26,10 @@ import { createAccount, isModularAccountV2 } from "../utils/createAccount.js";
26
26
  import { createDummySigner } from "../utils/createDummySigner.js";
27
27
  import { createAuthorization } from "../utils/7702.js";
28
28
  import { InvalidRequestError } from "ox/RpcResponse";
29
+ import {
30
+ parseDelegation,
31
+ assertValid7702AccountAddress,
32
+ } from "../utils/7702.js";
29
33
 
30
34
  export type CreateSessionParams = Omit<
31
35
  Static<
@@ -59,15 +63,26 @@ export async function createSession(
59
63
  throw new ChainNotFoundError();
60
64
  }
61
65
 
62
- const { counterfactualInfo, delegation } = await client.request({
63
- method: "wallet_requestAccount",
64
- params: [
65
- {
66
- accountAddress: params.account,
67
- includeCounterfactualInfo: true,
68
- },
69
- ],
70
- });
66
+ assertValid7702AccountAddress(
67
+ params.account,
68
+ params.capabilities?.eip7702Auth,
69
+ );
70
+
71
+ const { counterfactualInfo, delegation } = params.capabilities?.eip7702Auth
72
+ ? {
73
+ counterfactualInfo: undefined,
74
+ delegation: parseDelegation(params.capabilities.eip7702Auth),
75
+ }
76
+ : await client.request({
77
+ method: "wallet_requestAccount",
78
+ params: [
79
+ {
80
+ accountAddress: params.account,
81
+ includeCounterfactualInfo: true,
82
+ },
83
+ ],
84
+ });
85
+
71
86
  if (!counterfactualInfo && !delegation) {
72
87
  throw new InvalidRequestError({
73
88
  message:
@@ -104,7 +119,11 @@ export async function createSession(
104
119
  const { typedData, fullPreSignatureDeferredActionDigest } =
105
120
  await new PermissionBuilder({
106
121
  client: _client,
107
- key: params.key,
122
+ key: {
123
+ ...params.key,
124
+ // Alias 'ecdsa' to 'secp256k1'
125
+ type: params.key.type === "ecdsa" ? "secp256k1" : params.key.type,
126
+ },
108
127
  entityId,
109
128
  nonce,
110
129
  deadline: params.expiry,
@@ -6,6 +6,7 @@ import type { Static } from "@sinclair/typebox";
6
6
  import { Value } from "@sinclair/typebox/value";
7
7
  import {
8
8
  ChainNotFoundError,
9
+ hexToNumber,
9
10
  isHex,
10
11
  type Chain,
11
12
  type Hex,
@@ -16,6 +17,21 @@ import type { wallet_getCallsStatus } from "../../rpc/request.js";
16
17
  import type { WalletServerViemRpcSchema } from "../../rpc/schema.js";
17
18
  import { TypeCallId } from "../../schemas.js";
18
19
  import { castToHex } from "../../utils.js";
20
+ import { InternalError, BaseError } from "ox/RpcResponse";
21
+ import {
22
+ polygon,
23
+ mainnet,
24
+ base,
25
+ worldchain,
26
+ optimism,
27
+ arbitrum,
28
+ sepolia,
29
+ polygonAmoy,
30
+ baseSepolia,
31
+ optimismSepolia,
32
+ worldchainSepolia,
33
+ arbitrumSepolia,
34
+ } from "viem/chains";
19
35
 
20
36
  export type GetCallsStatusParams = Static<
21
37
  (typeof wallet_getCallsStatus)["properties"]["Request"]["properties"]["params"]
@@ -44,6 +60,29 @@ export const CallStatusCode = {
44
60
  PARTIAL_CHAIN_RULES_FAILURE: 600,
45
61
  } as const;
46
62
 
63
+ // https://eips.ethereum.org/EIPS/eip-5792#error-codes
64
+ const ErrorCode = {
65
+ UNKNOWN_BUNDLE_ID: 5730,
66
+ };
67
+
68
+ // "eth_getUserOperationByHash" is limited to the last 150 blocks
69
+ // for all networks except those in this list.
70
+ // https://www.alchemy.com/docs/node/bundler-api/bundler-api-endpoints/eth-get-user-operation-by-hash
71
+ const GET_USER_OP_BY_HASH_UNLIMITED_RANGE_NETWORKS: number[] = [
72
+ mainnet.id,
73
+ sepolia.id,
74
+ polygon.id,
75
+ polygonAmoy.id,
76
+ base.id,
77
+ baseSepolia.id,
78
+ optimism.id,
79
+ optimismSepolia.id,
80
+ worldchain.id,
81
+ worldchainSepolia.id,
82
+ arbitrum.id,
83
+ arbitrumSepolia.id,
84
+ ];
85
+
47
86
  export async function getCallsStatus(
48
87
  client: SmartAccountClient<
49
88
  Transport,
@@ -57,21 +96,54 @@ export async function getCallsStatus(
57
96
  if (!client.chain) {
58
97
  throw new ChainNotFoundError();
59
98
  }
60
-
61
99
  const { chainId, hash } = Value.Decode(TypeCallId, callId);
62
100
 
63
- const result = await client.getUserOperationReceipt(hash);
64
-
65
- return {
101
+ const baseResp = {
66
102
  id: callId,
67
103
  chainId,
68
104
  atomic: true,
69
- status: !result?.receipt
70
- ? CallStatusCode.PENDING
71
- : result.success
72
- ? CallStatusCode.CONFIRMED
73
- : CallStatusCode.CHAIN_RULES_FAILURE,
74
- receipts: !result?.receipt ? undefined : [transformReceipt(result.receipt)],
105
+ };
106
+
107
+ const result = await client.getUserOperationByHash(hash);
108
+ if (
109
+ !result &&
110
+ GET_USER_OP_BY_HASH_UNLIMITED_RANGE_NETWORKS.includes(hexToNumber(chainId))
111
+ ) {
112
+ // This network has unlimited range, so we should always have a result here if the callId is valid.
113
+ throw new BaseError({
114
+ message: `callId ${callId} not found`,
115
+ code: ErrorCode.UNKNOWN_BUNDLE_ID,
116
+ });
117
+ }
118
+ if (result && !result.transactionHash) {
119
+ // A result but no txn hash means it's valid but pending.
120
+ return {
121
+ ...baseResp,
122
+ status: CallStatusCode.PENDING,
123
+ };
124
+ }
125
+
126
+ const receipt = await client.getUserOperationReceipt(hash);
127
+ if (result?.transactionHash && !receipt) {
128
+ // This should never happen.
129
+ throw new InternalError({
130
+ message: `Failed to get receipt for callId ${callId}`,
131
+ });
132
+ }
133
+ if (!receipt) {
134
+ // This covers txns older than 150 blocks which were not retrievable by "eth_getUserOperationByHash".
135
+ throw new BaseError({
136
+ message: `callId ${callId} not found`,
137
+ code: ErrorCode.UNKNOWN_BUNDLE_ID,
138
+ });
139
+ }
140
+
141
+ return {
142
+ ...baseResp,
143
+ status: receipt.success
144
+ ? CallStatusCode.CONFIRMED
145
+ : CallStatusCode.CHAIN_RULES_FAILURE,
146
+ receipts: [transformReceipt(receipt.receipt)],
75
147
  };
76
148
  }
77
149
 
@@ -17,8 +17,9 @@ import type { wallet_prepareCalls } from "../../rpc/request.js";
17
17
  import type { WalletServerViemRpcSchema } from "../../rpc/schema.js";
18
18
  import { createAccount } from "../utils/createAccount.js";
19
19
  import { createDummySigner } from "../utils/createDummySigner.js";
20
- import { createAuthorization } from "../utils/7702.js";
20
+ import { createAuthorization, parseDelegation } from "../utils/7702.js";
21
21
  import { InvalidRequestError } from "ox/RpcResponse";
22
+ import { assertValid7702AccountAddress } from "../utils/7702.js";
22
23
 
23
24
  export type PrepareCallsParams = Omit<
24
25
  Static<
@@ -45,16 +46,23 @@ export async function prepareCalls(
45
46
  throw new ChainNotFoundError();
46
47
  }
47
48
 
49
+ assertValid7702AccountAddress(params.from, params.capabilities?.eip7702Auth);
50
+
48
51
  // in local mode, we probably want some kind of caching for this
49
- const { counterfactualInfo, delegation } = await client.request({
50
- method: "wallet_requestAccount",
51
- params: [
52
- {
53
- accountAddress: params.from,
54
- includeCounterfactualInfo: true,
55
- },
56
- ],
57
- });
52
+ const { counterfactualInfo, delegation } = params.capabilities?.eip7702Auth
53
+ ? {
54
+ counterfactualInfo: undefined,
55
+ delegation: parseDelegation(params.capabilities.eip7702Auth),
56
+ }
57
+ : await client.request({
58
+ method: "wallet_requestAccount",
59
+ params: [
60
+ {
61
+ accountAddress: params.from,
62
+ includeCounterfactualInfo: true,
63
+ },
64
+ ],
65
+ });
58
66
 
59
67
  if (!counterfactualInfo && !delegation) {
60
68
  throw new InvalidRequestError({
@@ -69,7 +77,7 @@ export async function prepareCalls(
69
77
  signer: createDummySigner(params.from),
70
78
  accountAddress: params.from,
71
79
  counterfactualInfo,
72
- capabilities: params.capabilities,
80
+ permissions: params.capabilities?.permissions,
73
81
  delegation,
74
82
  });
75
83
 
@@ -19,7 +19,7 @@ import { decodePermissionsContext } from "../../capabilities/permissions/mav2.js
19
19
  import type { wallet_sendPreparedCalls } from "../../rpc/request.js";
20
20
  import type { WalletServerViemRpcSchema } from "../../rpc/schema.js";
21
21
  import { TypeCallId } from "../../schemas.js";
22
- import { isSupportedImplementationAddress7702 } from "../utils/7702.js";
22
+ import { isSupportedDelegationAddress7702 } from "../utils/7702.js";
23
23
  import { InvalidRequestError } from "ox/RpcResponse";
24
24
 
25
25
  export type SendPreparedCallsParams = Omit<
@@ -51,7 +51,7 @@ export async function sendPreparedCalls(
51
51
  // One last safety check to be sure the UO wasn't modified to include an unsupported 7702 delegation address.
52
52
  if (
53
53
  params.signedAuthorization &&
54
- !isSupportedImplementationAddress7702(params.signedAuthorization.address)
54
+ !isSupportedDelegationAddress7702(params.signedAuthorization.address)
55
55
  ) {
56
56
  throw new InvalidRequestError({
57
57
  message: `Unsupported 7702 delegation address: ${params.signedAuthorization.address}`,
@@ -5,8 +5,12 @@ import {
5
5
  type Address,
6
6
  type Chain,
7
7
  type Transport,
8
+ isAddress,
8
9
  } from "viem";
9
10
  import type { WalletServerViemRpcSchema } from "../../rpc/schema.js";
11
+ import type { Eip7702AuthCapability } from "../../capabilities/eip7702Auth.ts";
12
+ import type { Static } from "@sinclair/typebox";
13
+ import { InvalidRequestError } from "ox/RpcResponse";
10
14
 
11
15
  export const createAuthorization = async (
12
16
  client: SmartAccountClient<
@@ -32,27 +36,71 @@ export const createAuthorization = async (
32
36
  };
33
37
  };
34
38
 
35
- type Supported7702AccountType = "ModularAccountV2";
39
+ export const EIP_7702_ACCOUNT_TYPE = ["ModularAccountV2"] as const;
36
40
 
37
- const IMPLEMENTATION_ADDRESS_TO_ACCOUNT_TYPE: Record<
41
+ type Supported7702AccountType = (typeof EIP_7702_ACCOUNT_TYPE)[number];
42
+
43
+ const Eip7702AccountTypeToDelegationAddress = {
44
+ ModularAccountV2: "0x69007702764179f14F51cdce752f4f775d74E139",
45
+ } as const satisfies Record<Supported7702AccountType, Address>;
46
+
47
+ const DelegationAddressToAccountType: Record<
38
48
  Address,
39
49
  Supported7702AccountType
40
- > = {
41
- "0x69007702764179f14F51cdce752f4f775d74E139": "ModularAccountV2",
50
+ > = Object.fromEntries(
51
+ Object.entries(Eip7702AccountTypeToDelegationAddress).map(([key, value]) => [
52
+ value,
53
+ key,
54
+ ]),
55
+ ) as Record<Address, Supported7702AccountType>;
56
+
57
+ export const SUPPORTED_DELEGATION_ADDRESSES = Object.values(
58
+ Eip7702AccountTypeToDelegationAddress,
59
+ );
60
+
61
+ export const isSupportedDelegationAddress7702 = (address: Address): boolean => {
62
+ return (SUPPORTED_DELEGATION_ADDRESSES as Address[]).includes(address);
42
63
  };
43
64
 
44
- export const getAccountTypeForImplementationAddress7702 = (
65
+ export const getAccountTypeForDelegationAddress7702 = (
45
66
  address: Address,
46
67
  ): Supported7702AccountType | undefined => {
47
- return IMPLEMENTATION_ADDRESS_TO_ACCOUNT_TYPE[address];
68
+ return DelegationAddressToAccountType[address];
48
69
  };
49
70
 
50
- const SUPPORTED_IMPLEMENTATION_ADDRESSES = Object.keys(
51
- IMPLEMENTATION_ADDRESS_TO_ACCOUNT_TYPE,
52
- );
71
+ const getDelegationAddressForAccountType7702 = (
72
+ accountType: Supported7702AccountType,
73
+ ): (typeof SUPPORTED_DELEGATION_ADDRESSES)[number] => {
74
+ return Eip7702AccountTypeToDelegationAddress[accountType];
75
+ };
76
+
77
+ const DEFAULT_7702_DELEGATION_ADDR =
78
+ Eip7702AccountTypeToDelegationAddress["ModularAccountV2"];
53
79
 
54
- export const isSupportedImplementationAddress7702 = (
55
- address: string,
56
- ): boolean => {
57
- return SUPPORTED_IMPLEMENTATION_ADDRESSES.includes(address);
80
+ export const parseDelegation = (
81
+ eip7702AuthCapability: Static<typeof Eip7702AuthCapability>,
82
+ ) => {
83
+ return eip7702AuthCapability === true
84
+ ? DEFAULT_7702_DELEGATION_ADDR
85
+ : isAddress(eip7702AuthCapability.delegation)
86
+ ? eip7702AuthCapability.delegation
87
+ : getDelegationAddressForAccountType7702(
88
+ eip7702AuthCapability.delegation,
89
+ );
90
+ };
91
+
92
+ export const assertValid7702AccountAddress = (
93
+ fromAddress: Address,
94
+ eip7702AuthCapability: Static<typeof Eip7702AuthCapability> | undefined,
95
+ ) => {
96
+ if (
97
+ eip7702AuthCapability &&
98
+ typeof eip7702AuthCapability === "object" &&
99
+ "account" in eip7702AuthCapability &&
100
+ eip7702AuthCapability?.account !== fromAddress
101
+ ) {
102
+ throw new InvalidRequestError({
103
+ message: `EIP-7702 delegation account ${eip7702AuthCapability.account} must match 'from' address ${fromAddress}.`,
104
+ });
105
+ }
58
106
  };
@@ -6,12 +6,12 @@ import {
6
6
  import type { StaticDecode } from "@sinclair/typebox";
7
7
  import type { Address, Chain, Transport } from "viem";
8
8
  import { concatHex, hexToNumber } from "viem";
9
- import type { Capabilities } from "../../capabilities/index.js";
10
9
  import type { TypeSerializedInitcode } from "../../schemas.js";
11
10
  import { parsePermissionsContext } from "./parsePermissionsContext.js";
12
11
  import { assertNever } from "../../utils.js";
13
- import { getAccountTypeForImplementationAddress7702 } from "./7702.js";
12
+ import { getAccountTypeForDelegationAddress7702 } from "./7702.js";
14
13
  import { InternalError } from "ox/RpcResponse";
14
+ import { PermissionsCapability } from "../../capabilities/permissions/index.js";
15
15
 
16
16
  type CreateAccountParams = {
17
17
  chain: Chain;
@@ -19,8 +19,8 @@ type CreateAccountParams = {
19
19
  signer: SmartAccountSigner;
20
20
  accountAddress: Address;
21
21
  counterfactualInfo?: StaticDecode<typeof TypeSerializedInitcode>; // undefined for 7702 accounts
22
+ permissions?: StaticDecode<typeof PermissionsCapability>;
22
23
  delegation?: Address;
23
- capabilities?: StaticDecode<typeof Capabilities>;
24
24
  };
25
25
 
26
26
  /**
@@ -47,7 +47,7 @@ export async function createAccount(
47
47
  });
48
48
  }
49
49
  } else if (mode === "7702") {
50
- const accountType = getAccountTypeForImplementationAddress7702(
50
+ const accountType = getAccountTypeForDelegationAddress7702(
51
51
  params.delegation!,
52
52
  );
53
53
  if (accountType !== "ModularAccountV2") {
@@ -60,7 +60,7 @@ export async function createAccount(
60
60
  }
61
61
 
62
62
  const parsedContext = parsePermissionsContext(
63
- params.capabilities,
63
+ params.permissions,
64
64
  ci,
65
65
  params.delegation,
66
66
  );
@@ -2,33 +2,33 @@ import type { StaticDecode } from "@sinclair/typebox";
2
2
  import { InvalidRequestError } from "ox/RpcResponse";
3
3
  import { decodePermissionsContext } from "../../capabilities/permissions/mav2.js";
4
4
  import type { TypeSerializedInitcode } from "../../schemas.js";
5
- import type { PrepareCallsParams } from "../actions/prepareCalls.js";
6
5
  import type { Address } from "viem";
7
- import { getAccountTypeForImplementationAddress7702 } from "./7702.js";
6
+ import { getAccountTypeForDelegationAddress7702 } from "./7702.js";
7
+ import { PermissionsCapability } from "../../capabilities/permissions/index.js";
8
8
 
9
9
  export function parsePermissionsContext(
10
- capabilities: PrepareCallsParams["capabilities"],
11
- parsedCi: StaticDecode<typeof TypeSerializedInitcode> | undefined,
10
+ permissions?: StaticDecode<typeof PermissionsCapability>,
11
+ parsedCi?: StaticDecode<typeof TypeSerializedInitcode> | undefined,
12
12
  delegation7702?: Address,
13
13
  ) {
14
- if (!capabilities?.permissions) {
14
+ if (!permissions) {
15
15
  return undefined;
16
16
  }
17
17
 
18
- if ("sessionId" in capabilities.permissions) {
18
+ if ("sessionId" in permissions) {
19
19
  throw new InvalidRequestError({
20
20
  message: "Remote permissions are not supported in isomorphic client",
21
21
  });
22
22
  }
23
23
 
24
- if (!("context" in capabilities.permissions)) {
24
+ if (!("context" in permissions)) {
25
25
  return undefined;
26
26
  }
27
27
 
28
28
  const isMAV2 =
29
29
  (parsedCi && parsedCi.factoryType === "MAv2.0.0-sma-b") ||
30
30
  (delegation7702 &&
31
- getAccountTypeForImplementationAddress7702(delegation7702) ===
31
+ getAccountTypeForDelegationAddress7702(delegation7702) ===
32
32
  "ModularAccountV2");
33
33
 
34
34
  if (!isMAV2) {
@@ -37,7 +37,7 @@ export function parsePermissionsContext(
37
37
  });
38
38
  }
39
39
 
40
- const context = decodePermissionsContext(capabilities.permissions);
40
+ const context = decodePermissionsContext(permissions);
41
41
 
42
42
  if (context?.contextVersion === "REMOTE_MODE_DEFERRED_ACTION") {
43
43
  throw new InvalidRequestError({
@@ -1,6 +1,6 @@
1
1
  import { split } from "@aa-sdk/core";
2
2
  import { buildDeferredActionDigest } from "@account-kit/smart-contracts/experimental";
3
- import { createClient, custom, type Address, type JsonRpcAccount } from "viem";
3
+ import { createClient, custom, type Address } from "viem";
4
4
  import {
5
5
  encodePermissionsContext,
6
6
  prefixSignatureKeyType,
@@ -28,10 +28,8 @@ const localMethods = [
28
28
  type LocalMethod = (typeof localMethods)[number];
29
29
 
30
30
  export function createLocalClient<
31
- TAccount extends JsonRpcAccount<Address> | undefined =
32
- | JsonRpcAccount<Address>
33
- | undefined,
34
- >(params: CreateInnerClientParams<TAccount>): InnerWalletApiClient<TAccount>;
31
+ TAccount extends Address | undefined = Address | undefined,
32
+ >(params: CreateInnerClientParams<TAccount>): InnerWalletApiClient;
35
33
 
36
34
  export function createLocalClient(
37
35
  params: CreateInnerClientParams,
@@ -1,11 +1,5 @@
1
1
  import { Provider } from "ox";
2
- import {
3
- BaseError,
4
- createClient,
5
- custom,
6
- type Address,
7
- type JsonRpcAccount,
8
- } from "viem";
2
+ import { BaseError, createClient, custom, type Address } from "viem";
9
3
  import { encodePermissionsContext } from "../capabilities/permissions/mav2.js";
10
4
  import { signSignatureRequest } from "../client/actions/signSignatureRequest.js";
11
5
  import { internalStateDecorator } from "../internal/decorator.js";
@@ -17,18 +11,16 @@ import type {
17
11
  InnerWalletApiClientBase,
18
12
  } from "../types.ts";
19
13
 
20
- export function createRemoteClient<
21
- TAccount extends JsonRpcAccount<Address> | undefined =
22
- | JsonRpcAccount<Address>
23
- | undefined,
24
- >(params: CreateInnerClientParams<TAccount>): InnerWalletApiClient<TAccount>;
25
-
26
14
  /**
27
15
  * This is a low-level client just used to make RPC requests in remote mode
28
16
  * This should be wrapped by a higher-level smart account client that provides actions
29
17
  * that uses this client under the hood
30
18
  * @returns
31
19
  */
20
+ export function createRemoteClient<
21
+ TAccount extends Address | undefined = Address | undefined,
22
+ >(params: CreateInnerClientParams<TAccount>): InnerWalletApiClient;
23
+
32
24
  export function createRemoteClient(
33
25
  params: CreateInnerClientParams,
34
26
  ): InnerWalletApiClient {
@@ -16,8 +16,10 @@ import {
16
16
  TypeUserOperationRequest_v6,
17
17
  TypeUserOperationRequest_v7,
18
18
  TypeUuid,
19
+ TypeSignatureType,
19
20
  } from "../schemas.js";
20
21
  import { Examples } from "./examples.js";
22
+ import { Eip7702AuthCapability } from "../capabilities/eip7702Auth.js";
21
23
 
22
24
  export const wallet_sendPreparedCalls = Type.Object(
23
25
  {
@@ -43,15 +45,7 @@ export const wallet_sendPreparedCalls = Type.Object(
43
45
  ]),
44
46
  chainId: TypeHex(),
45
47
  signature: Type.Object({
46
- type: Type.Transform(Type.Literal("ecdsa"))
47
- .Decode((value) => {
48
- if (value.toLowerCase() !== "ecdsa") {
49
- throw new Error("Invalid signature type, must be 'ecdsa'");
50
- }
51
-
52
- return "ecdsa" as const;
53
- })
54
- .Encode((value) => value),
48
+ type: Type.Exclude(TypeSignatureType, Type.Literal("contract")),
55
49
  signature: TypeHex(),
56
50
  }),
57
51
  signedAuthorization: Type.Optional(TypeEip7702AuthExtendedFields),
@@ -235,6 +229,11 @@ export const wallet_createSession = Type.Object(
235
229
  PermissionsData,
236
230
  Type.Object({
237
231
  account: TypeAddress,
232
+ capabilities: Type.Optional(
233
+ Type.Object({
234
+ eip7702Auth: Type.Optional(Eip7702AuthCapability),
235
+ }),
236
+ ),
238
237
  }),
239
238
  ]),
240
239
  ]),
package/src/schemas.ts CHANGED
@@ -287,11 +287,15 @@ export type TypeAccountType = Exclude<
287
287
  undefined
288
288
  >["accountType"];
289
289
 
290
+ export const TypeSignatureType = Type.Union([
291
+ Type.Literal("secp256k1", { title: "Secp256k1" }),
292
+ Type.Literal("ecdsa", { title: "ECDSA (alias for secp256k1)" }),
293
+ Type.Literal("contract", { title: "Contract" }),
294
+ ]);
295
+ export type TypeSignatureType = Static<typeof TypeSignatureType>;
296
+
290
297
  export const KeySigner = Type.Object({
291
- type: Type.Union([
292
- Type.Literal("secp256k1", { title: "Secp256k1" }),
293
- Type.Literal("contract", { title: "Contract" }),
294
- ]),
298
+ type: TypeSignatureType,
295
299
  publicKey: TypeHex({}),
296
300
  });
297
301
  export type KeySigner = Static<typeof KeySigner>;