@account-kit/wallet-client 0.1.0-alpha.4 → 0.1.0-alpha.6
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/esm/capabilities/eip7702Auth.d.ts +4 -0
- package/dist/esm/capabilities/eip7702Auth.js +18 -0
- package/dist/esm/capabilities/eip7702Auth.js.map +1 -0
- package/dist/esm/capabilities/index.d.ts +4 -0
- package/dist/esm/capabilities/index.js +2 -0
- package/dist/esm/capabilities/index.js.map +1 -1
- package/dist/esm/capabilities/overrides.js +8 -8
- package/dist/esm/capabilities/overrides.js.map +1 -1
- package/dist/esm/capabilities/permissions/index.d.ts +2 -2
- package/dist/esm/capabilities/permissions/index.js +6 -3
- package/dist/esm/capabilities/permissions/index.js.map +1 -1
- package/dist/esm/capabilities/permissions/mav2.js +1 -0
- package/dist/esm/capabilities/permissions/mav2.js.map +1 -1
- package/dist/esm/client/actions/getCallsStatus.d.ts +1 -2
- package/dist/esm/client/actions/getCallsStatus.js +19 -0
- package/dist/esm/client/actions/getCallsStatus.js.map +1 -1
- package/dist/esm/client/actions/grantPermissions.d.ts +10 -65
- package/dist/esm/client/actions/grantPermissions.js +63 -4
- package/dist/esm/client/actions/grantPermissions.js.map +1 -1
- package/dist/esm/client/actions/prepareCalls.d.ts +4 -4
- package/dist/esm/client/actions/prepareCalls.js +38 -5
- package/dist/esm/client/actions/prepareCalls.js.map +1 -1
- package/dist/esm/client/actions/requestAccount.d.ts +3 -4
- package/dist/esm/client/actions/requestAccount.js +18 -1
- package/dist/esm/client/actions/requestAccount.js.map +1 -1
- package/dist/esm/client/actions/sendPreparedCalls.d.ts +6 -14
- package/dist/esm/client/actions/sendPreparedCalls.js +11 -12
- package/dist/esm/client/actions/sendPreparedCalls.js.map +1 -1
- package/dist/esm/client/actions/signMessage.d.ts +3 -3
- package/dist/esm/client/actions/signMessage.js +18 -0
- package/dist/esm/client/actions/signMessage.js.map +1 -1
- package/dist/esm/client/actions/signPreparedCalls.d.ts +14 -0
- package/dist/esm/client/actions/signPreparedCalls.js +53 -0
- package/dist/esm/client/actions/signPreparedCalls.js.map +1 -0
- package/dist/esm/client/actions/signSignatureRequest.d.ts +9 -8
- package/dist/esm/client/actions/signSignatureRequest.js +69 -31
- package/dist/esm/client/actions/signSignatureRequest.js.map +1 -1
- package/dist/esm/client/actions/signTypedData.d.ts +2 -2
- package/dist/esm/client/actions/signTypedData.js +31 -0
- package/dist/esm/client/actions/signTypedData.js.map +1 -1
- package/dist/esm/client/client.e2e-test.js +47 -44
- package/dist/esm/client/client.e2e-test.js.map +1 -1
- package/dist/esm/client/decorator.d.ts +7 -5
- package/dist/esm/client/decorator.js +3 -1
- package/dist/esm/client/decorator.js.map +1 -1
- package/dist/esm/client/index.d.ts +35 -10
- package/dist/esm/client/index.js +0 -29
- package/dist/esm/client/index.js.map +1 -1
- package/dist/esm/exports/index.d.ts +2 -1
- package/dist/esm/exports/index.js +2 -1
- package/dist/esm/exports/index.js.map +1 -1
- package/dist/esm/isomorphic/actions/createSession.js +15 -18
- package/dist/esm/isomorphic/actions/createSession.js.map +1 -1
- package/dist/esm/isomorphic/actions/getCallsStatus.js +62 -9
- package/dist/esm/isomorphic/actions/getCallsStatus.js.map +1 -1
- package/dist/esm/isomorphic/actions/prepareCalls.js +39 -26
- package/dist/esm/isomorphic/actions/prepareCalls.js.map +1 -1
- package/dist/esm/isomorphic/actions/sendPreparedCalls.d.ts +3 -3
- package/dist/esm/isomorphic/actions/sendPreparedCalls.js +77 -37
- package/dist/esm/isomorphic/actions/sendPreparedCalls.js.map +1 -1
- package/dist/esm/isomorphic/client.d.ts +139 -13
- package/dist/esm/isomorphic/utils/7702.d.ts +13 -6
- package/dist/esm/isomorphic/utils/7702.js +48 -13
- package/dist/esm/isomorphic/utils/7702.js.map +1 -1
- package/dist/esm/isomorphic/utils/createAccount.d.ts +2 -2
- package/dist/esm/isomorphic/utils/createAccount.js +4 -3
- package/dist/esm/isomorphic/utils/createAccount.js.map +1 -1
- package/dist/esm/isomorphic/utils/decodeSignature.d.ts +3 -0
- package/dist/esm/isomorphic/utils/decodeSignature.js +13 -0
- package/dist/esm/isomorphic/utils/decodeSignature.js.map +1 -0
- package/dist/esm/isomorphic/utils/parsePermissionsContext.d.ts +2 -2
- package/dist/esm/isomorphic/utils/parsePermissionsContext.js +8 -7
- package/dist/esm/isomorphic/utils/parsePermissionsContext.js.map +1 -1
- package/dist/esm/local/client.d.ts +2 -2
- package/dist/esm/local/client.js +2 -3
- package/dist/esm/local/client.js.map +1 -1
- package/dist/esm/remote/client.d.ts +8 -2
- package/dist/esm/remote/client.js +3 -13
- package/dist/esm/remote/client.js.map +1 -1
- package/dist/esm/rpc/examples.d.ts +3 -3
- package/dist/esm/rpc/examples.js +3 -3
- package/dist/esm/rpc/examples.js.map +1 -1
- package/dist/esm/rpc/request.d.ts +362 -44
- package/dist/esm/rpc/request.js +26 -56
- package/dist/esm/rpc/request.js.map +1 -1
- package/dist/esm/rpc/schema.d.ts +325 -49
- package/dist/esm/rpc/schema.js.map +1 -1
- package/dist/esm/schemas.d.ts +454 -14
- package/dist/esm/schemas.js +168 -53
- package/dist/esm/schemas.js.map +1 -1
- package/dist/esm/types.d.ts +10 -10
- package/dist/esm/types.js.map +1 -1
- package/dist/types/capabilities/eip7702Auth.d.ts +5 -0
- package/dist/types/capabilities/eip7702Auth.d.ts.map +1 -0
- package/dist/types/capabilities/index.d.ts +4 -0
- package/dist/types/capabilities/index.d.ts.map +1 -1
- package/dist/types/capabilities/permissions/index.d.ts +2 -2
- package/dist/types/capabilities/permissions/index.d.ts.map +1 -1
- package/dist/types/capabilities/permissions/mav2.d.ts.map +1 -1
- package/dist/types/client/actions/getCallsStatus.d.ts +1 -2
- package/dist/types/client/actions/getCallsStatus.d.ts.map +1 -1
- package/dist/types/client/actions/grantPermissions.d.ts +10 -65
- package/dist/types/client/actions/grantPermissions.d.ts.map +1 -1
- package/dist/types/client/actions/prepareCalls.d.ts +4 -4
- package/dist/types/client/actions/prepareCalls.d.ts.map +1 -1
- package/dist/types/client/actions/requestAccount.d.ts +3 -4
- package/dist/types/client/actions/requestAccount.d.ts.map +1 -1
- package/dist/types/client/actions/sendPreparedCalls.d.ts +6 -14
- package/dist/types/client/actions/sendPreparedCalls.d.ts.map +1 -1
- package/dist/types/client/actions/signMessage.d.ts +3 -3
- package/dist/types/client/actions/signMessage.d.ts.map +1 -1
- package/dist/types/client/actions/signPreparedCalls.d.ts +15 -0
- package/dist/types/client/actions/signPreparedCalls.d.ts.map +1 -0
- package/dist/types/client/actions/signSignatureRequest.d.ts +9 -8
- package/dist/types/client/actions/signSignatureRequest.d.ts.map +1 -1
- package/dist/types/client/actions/signTypedData.d.ts +2 -2
- package/dist/types/client/actions/signTypedData.d.ts.map +1 -1
- package/dist/types/client/decorator.d.ts +7 -5
- package/dist/types/client/decorator.d.ts.map +1 -1
- package/dist/types/client/index.d.ts +35 -10
- package/dist/types/client/index.d.ts.map +1 -1
- package/dist/types/exports/index.d.ts +2 -1
- package/dist/types/exports/index.d.ts.map +1 -1
- package/dist/types/isomorphic/actions/createSession.d.ts.map +1 -1
- package/dist/types/isomorphic/actions/getCallsStatus.d.ts.map +1 -1
- package/dist/types/isomorphic/actions/prepareCalls.d.ts.map +1 -1
- package/dist/types/isomorphic/actions/sendPreparedCalls.d.ts +3 -3
- package/dist/types/isomorphic/actions/sendPreparedCalls.d.ts.map +1 -1
- package/dist/types/isomorphic/client.d.ts +139 -13
- package/dist/types/isomorphic/client.d.ts.map +1 -1
- package/dist/types/isomorphic/utils/7702.d.ts +13 -6
- package/dist/types/isomorphic/utils/7702.d.ts.map +1 -1
- package/dist/types/isomorphic/utils/createAccount.d.ts +2 -2
- package/dist/types/isomorphic/utils/createAccount.d.ts.map +1 -1
- package/dist/types/isomorphic/utils/decodeSignature.d.ts +4 -0
- package/dist/types/isomorphic/utils/decodeSignature.d.ts.map +1 -0
- package/dist/types/isomorphic/utils/parsePermissionsContext.d.ts +2 -2
- package/dist/types/isomorphic/utils/parsePermissionsContext.d.ts.map +1 -1
- package/dist/types/local/client.d.ts +2 -2
- package/dist/types/local/client.d.ts.map +1 -1
- package/dist/types/remote/client.d.ts +8 -2
- package/dist/types/remote/client.d.ts.map +1 -1
- package/dist/types/rpc/examples.d.ts +3 -3
- package/dist/types/rpc/examples.d.ts.map +1 -1
- package/dist/types/rpc/request.d.ts +362 -44
- package/dist/types/rpc/request.d.ts.map +1 -1
- package/dist/types/rpc/schema.d.ts +325 -49
- package/dist/types/rpc/schema.d.ts.map +1 -1
- package/dist/types/schemas.d.ts +454 -14
- package/dist/types/schemas.d.ts.map +1 -1
- package/dist/types/types.d.ts +10 -10
- package/dist/types/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/capabilities/eip7702Auth.ts +26 -0
- package/src/capabilities/index.ts +2 -0
- package/src/capabilities/overrides.ts +8 -8
- package/src/capabilities/permissions/index.ts +8 -3
- package/src/capabilities/permissions/mav2.ts +1 -0
- package/src/client/actions/getCallsStatus.ts +0 -10
- package/src/client/actions/grantPermissions.ts +16 -84
- package/src/client/actions/prepareCalls.ts +18 -23
- package/src/client/actions/requestAccount.ts +9 -26
- package/src/client/actions/sendPreparedCalls.ts +17 -17
- package/src/client/actions/signMessage.ts +2 -17
- package/src/client/actions/signPreparedCalls.ts +71 -0
- package/src/client/actions/signSignatureRequest.ts +51 -47
- package/src/client/actions/signTypedData.ts +1 -16
- package/src/client/client.e2e-test.ts +54 -57
- package/src/client/decorator.ts +19 -15
- package/src/client/index.ts +16 -39
- package/src/exports/index.ts +2 -1
- package/src/isomorphic/actions/createSession.ts +17 -20
- package/src/isomorphic/actions/getCallsStatus.ts +82 -10
- package/src/isomorphic/actions/prepareCalls.ts +43 -27
- package/src/isomorphic/actions/sendPreparedCalls.ts +105 -55
- package/src/isomorphic/utils/7702.ts +79 -21
- package/src/isomorphic/utils/createAccount.ts +5 -5
- package/src/isomorphic/utils/decodeSignature.ts +18 -0
- package/src/isomorphic/utils/parsePermissionsContext.ts +9 -9
- package/src/local/client.ts +5 -11
- package/src/remote/client.ts +7 -22
- package/src/rpc/examples.ts +3 -4
- package/src/rpc/request.ts +41 -64
- package/src/rpc/schema.ts +2 -2
- package/src/schemas.ts +232 -54
- package/src/types.ts +9 -21
|
@@ -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
|
|
64
|
-
|
|
65
|
-
return {
|
|
101
|
+
const baseResp = {
|
|
66
102
|
id: callId,
|
|
67
103
|
chainId,
|
|
68
104
|
atomic: true,
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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,10 @@ 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 {
|
|
20
|
+
import { createAuthorizationRequest, parseDelegation } from "../utils/7702.js";
|
|
21
21
|
import { InvalidRequestError } from "ox/RpcResponse";
|
|
22
|
+
import { assertNever } from "../../utils.js";
|
|
23
|
+
import { assertValid7702AccountAddress } from "../utils/7702.js";
|
|
22
24
|
|
|
23
25
|
export type PrepareCallsParams = Omit<
|
|
24
26
|
Static<
|
|
@@ -45,16 +47,23 @@ export async function prepareCalls(
|
|
|
45
47
|
throw new ChainNotFoundError();
|
|
46
48
|
}
|
|
47
49
|
|
|
50
|
+
assertValid7702AccountAddress(params.from, params.capabilities?.eip7702Auth);
|
|
51
|
+
|
|
48
52
|
// in local mode, we probably want some kind of caching for this
|
|
49
|
-
const { counterfactualInfo, delegation } =
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
53
|
+
const { counterfactualInfo, delegation } = params.capabilities?.eip7702Auth
|
|
54
|
+
? {
|
|
55
|
+
counterfactualInfo: undefined,
|
|
56
|
+
delegation: parseDelegation(params.capabilities.eip7702Auth),
|
|
57
|
+
}
|
|
58
|
+
: await client.request({
|
|
59
|
+
method: "wallet_requestAccount",
|
|
60
|
+
params: [
|
|
61
|
+
{
|
|
62
|
+
accountAddress: params.from,
|
|
63
|
+
includeCounterfactualInfo: true,
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
});
|
|
58
67
|
|
|
59
68
|
if (!counterfactualInfo && !delegation) {
|
|
60
69
|
throw new InvalidRequestError({
|
|
@@ -69,13 +78,13 @@ export async function prepareCalls(
|
|
|
69
78
|
signer: createDummySigner(params.from),
|
|
70
79
|
accountAddress: params.from,
|
|
71
80
|
counterfactualInfo,
|
|
72
|
-
|
|
81
|
+
permissions: params.capabilities?.permissions,
|
|
73
82
|
delegation,
|
|
74
83
|
});
|
|
75
84
|
|
|
76
85
|
// If using 7702, we need an Authorization (unless it's already authorized).
|
|
77
86
|
const authorizationRequest = delegation
|
|
78
|
-
? await
|
|
87
|
+
? await createAuthorizationRequest(client, {
|
|
79
88
|
address: account.address,
|
|
80
89
|
delegation,
|
|
81
90
|
})
|
|
@@ -99,29 +108,36 @@ export async function prepareCalls(
|
|
|
99
108
|
});
|
|
100
109
|
|
|
101
110
|
// The eip7702Auth field should never be included in the UO sig
|
|
102
|
-
// request. It's handled by
|
|
111
|
+
// request. It's handled by a separate authorization request.
|
|
103
112
|
if ("eip7702Auth" in builtUo) {
|
|
104
113
|
builtUo.eip7702Auth = undefined;
|
|
105
114
|
}
|
|
106
|
-
const uoRequest = deepHexlify(builtUo);
|
|
107
115
|
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
raw: account.getEntryPoint().getUserOperationHash(uoRequest),
|
|
112
|
-
},
|
|
113
|
-
};
|
|
116
|
+
const hexlifiedUo = deepHexlify(builtUo);
|
|
117
|
+
|
|
118
|
+
const ep = account.getEntryPoint();
|
|
114
119
|
|
|
115
|
-
|
|
120
|
+
const uoRequest = {
|
|
116
121
|
type:
|
|
117
|
-
|
|
118
|
-
? "user-operation-v070"
|
|
119
|
-
: "
|
|
120
|
-
|
|
122
|
+
ep.version === "0.7.0"
|
|
123
|
+
? ("user-operation-v070" as const)
|
|
124
|
+
: ep.version === "0.6.0"
|
|
125
|
+
? ("user-operation-v060" as const)
|
|
126
|
+
: assertNever(ep.version, "Unexpected entry point version"),
|
|
127
|
+
data: hexlifiedUo,
|
|
121
128
|
chainId: toHex(client.chain.id),
|
|
122
129
|
signatureRequest: {
|
|
123
|
-
|
|
124
|
-
|
|
130
|
+
type: "personal_sign" as const,
|
|
131
|
+
data: {
|
|
132
|
+
raw: ep.getUserOperationHash(hexlifiedUo),
|
|
133
|
+
},
|
|
125
134
|
},
|
|
126
135
|
};
|
|
136
|
+
|
|
137
|
+
return authorizationRequest
|
|
138
|
+
? {
|
|
139
|
+
type: "array" as const,
|
|
140
|
+
data: [authorizationRequest, uoRequest],
|
|
141
|
+
}
|
|
142
|
+
: uoRequest;
|
|
127
143
|
}
|
|
@@ -3,31 +3,33 @@ import {
|
|
|
3
3
|
type SmartAccountClient,
|
|
4
4
|
type SmartContractAccount,
|
|
5
5
|
} from "@aa-sdk/core";
|
|
6
|
-
import type { Static, StaticDecode } from "@sinclair/typebox";
|
|
7
6
|
import { Value } from "@sinclair/typebox/value";
|
|
8
7
|
import {
|
|
9
8
|
BaseError,
|
|
10
9
|
ChainNotFoundError,
|
|
11
10
|
concat,
|
|
12
11
|
concatHex,
|
|
12
|
+
numberToHex,
|
|
13
|
+
parseSignature,
|
|
13
14
|
toHex,
|
|
15
|
+
type Address,
|
|
14
16
|
type Chain,
|
|
15
17
|
type Hex,
|
|
16
18
|
type Transport,
|
|
17
19
|
} from "viem";
|
|
18
20
|
import { decodePermissionsContext } from "../../capabilities/permissions/mav2.js";
|
|
19
|
-
import type
|
|
21
|
+
import { type wallet_sendPreparedCalls } from "../../rpc/request.js";
|
|
20
22
|
import type { WalletServerViemRpcSchema } from "../../rpc/schema.js";
|
|
21
23
|
import { TypeCallId } from "../../schemas.js";
|
|
22
|
-
import {
|
|
24
|
+
import { isSupportedDelegationAddress7702 } from "../utils/7702.js";
|
|
23
25
|
import { InvalidRequestError } from "ox/RpcResponse";
|
|
26
|
+
import { assertNever } from "../../utils.js";
|
|
27
|
+
import type { Static } from "@sinclair/typebox";
|
|
28
|
+
import { decodeSignature } from "../utils/decodeSignature.js";
|
|
24
29
|
|
|
25
|
-
export type SendPreparedCallsParams =
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
>[0],
|
|
29
|
-
"chainId"
|
|
30
|
-
>;
|
|
30
|
+
export type SendPreparedCallsParams = Static<
|
|
31
|
+
(typeof wallet_sendPreparedCalls)["properties"]["Request"]["properties"]["params"]
|
|
32
|
+
>[0];
|
|
31
33
|
|
|
32
34
|
export type SendPreparedCallsResult = Static<
|
|
33
35
|
(typeof wallet_sendPreparedCalls)["properties"]["ReturnType"]
|
|
@@ -48,16 +50,6 @@ export async function sendPreparedCalls(
|
|
|
48
50
|
throw new ChainNotFoundError();
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
// One last safety check to be sure the UO wasn't modified to include an unsupported 7702 delegation address.
|
|
52
|
-
if (
|
|
53
|
-
params.signedAuthorization &&
|
|
54
|
-
!isSupportedImplementationAddress7702(params.signedAuthorization.address)
|
|
55
|
-
) {
|
|
56
|
-
throw new InvalidRequestError({
|
|
57
|
-
message: `Unsupported 7702 delegation address: ${params.signedAuthorization.address}`,
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
53
|
const deferredAction: Hex | undefined = (() => {
|
|
62
54
|
if (!params.capabilities?.permissions) {
|
|
63
55
|
return;
|
|
@@ -77,46 +69,104 @@ export async function sendPreparedCalls(
|
|
|
77
69
|
return decodedContext.deferredAction;
|
|
78
70
|
})();
|
|
79
71
|
|
|
80
|
-
const
|
|
81
|
-
params.type === "
|
|
82
|
-
?
|
|
83
|
-
|
|
72
|
+
const userOps =
|
|
73
|
+
params.type === "array"
|
|
74
|
+
? params.data.filter((it) => {
|
|
75
|
+
const isUserOp =
|
|
76
|
+
it.type === "user-operation-v060" ||
|
|
77
|
+
it.type === "user-operation-v070";
|
|
78
|
+
if (isUserOp && it.chainId !== toHex(client.chain.id)) {
|
|
79
|
+
throw new InvalidRequestError({
|
|
80
|
+
message:
|
|
81
|
+
"Multiple chain IDs in a single request are not currently supported.",
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
return isUserOp;
|
|
85
|
+
})
|
|
86
|
+
: [params];
|
|
87
|
+
|
|
88
|
+
const authorizations =
|
|
89
|
+
params.type === "array"
|
|
90
|
+
? params.data.filter((it) => it.type === "authorization")
|
|
91
|
+
: [];
|
|
84
92
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
signature:
|
|
90
|
-
deferredAction != null
|
|
91
|
-
? concatHex([
|
|
92
|
-
`0x${deferredAction.slice(68)}`, // Cuts off stuff preprended to the digest (nonce, etc. that we had previously).
|
|
93
|
-
"0xff",
|
|
94
|
-
"0x00",
|
|
95
|
-
params.signature.signature,
|
|
96
|
-
])
|
|
97
|
-
: concat(["0xFF", "0x00", params.signature.signature]),
|
|
98
|
-
eip7702Auth: params.signedAuthorization,
|
|
99
|
-
},
|
|
100
|
-
entryPoint.address,
|
|
101
|
-
)
|
|
102
|
-
.catch((err) => {
|
|
103
|
-
if (
|
|
104
|
-
err instanceof BaseError &&
|
|
105
|
-
err.details.endsWith("is not a contract and initCode is empty")
|
|
106
|
-
) {
|
|
107
|
-
throw new BaseError(
|
|
108
|
-
`${err.details} (If using 7702, be sure you include the 'signedAuthorization' field in the request parameters)`,
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
throw err;
|
|
93
|
+
if (authorizations.length > 1) {
|
|
94
|
+
throw new InvalidRequestError({
|
|
95
|
+
message:
|
|
96
|
+
"Multiple authorizations in a single request are not currently supported",
|
|
112
97
|
});
|
|
98
|
+
}
|
|
99
|
+
const [authorization] = authorizations;
|
|
100
|
+
|
|
101
|
+
// One last safety check to be sure the UO wasn't modified to include an unsupported 7702 delegation address.
|
|
102
|
+
if (
|
|
103
|
+
authorization &&
|
|
104
|
+
!isSupportedDelegationAddress7702(authorization.data.address)
|
|
105
|
+
) {
|
|
106
|
+
throw new InvalidRequestError({
|
|
107
|
+
message: `Unsupported 7702 delegation address: ${authorization.data.address}`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
113
110
|
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
111
|
+
const hashes = await Promise.all(
|
|
112
|
+
userOps.map(async (userOp, idx) => {
|
|
113
|
+
const ep: { address: Address } =
|
|
114
|
+
userOp.type === "user-operation-v060"
|
|
115
|
+
? getEntryPoint(client.chain, { version: "0.6.0" })
|
|
116
|
+
: userOp.type === "user-operation-v070"
|
|
117
|
+
? getEntryPoint(client.chain, { version: "0.7.0" })
|
|
118
|
+
: assertNever(userOp, "Unexpected user op type");
|
|
119
|
+
const authSig = authorization
|
|
120
|
+
? parseSignature(decodeSignature(authorization.signature).data)
|
|
121
|
+
: undefined;
|
|
122
|
+
const uoSigHex = decodeSignature(userOp.signature).data;
|
|
123
|
+
return client
|
|
124
|
+
.sendRawUserOperation(
|
|
125
|
+
{
|
|
126
|
+
...userOp.data,
|
|
127
|
+
signature:
|
|
128
|
+
deferredAction != null
|
|
129
|
+
? concatHex([
|
|
130
|
+
`0x${deferredAction.slice(68)}`, // Cuts off stuff prepended to the digest (nonce, etc. that we had previously).
|
|
131
|
+
"0xff",
|
|
132
|
+
"0x00",
|
|
133
|
+
uoSigHex,
|
|
134
|
+
])
|
|
135
|
+
: concat(["0xFF", "0x00", uoSigHex]),
|
|
136
|
+
eip7702Auth:
|
|
137
|
+
idx === 0 && authorization && authSig
|
|
138
|
+
? {
|
|
139
|
+
...authorization.data,
|
|
140
|
+
chainId: authorization.chainId,
|
|
141
|
+
...{
|
|
142
|
+
...authSig,
|
|
143
|
+
yParity: numberToHex(authSig.yParity),
|
|
144
|
+
},
|
|
145
|
+
}
|
|
146
|
+
: undefined,
|
|
147
|
+
},
|
|
148
|
+
ep.address,
|
|
149
|
+
)
|
|
150
|
+
.catch((err) => {
|
|
151
|
+
if (
|
|
152
|
+
err instanceof BaseError &&
|
|
153
|
+
err.details.endsWith("is not a contract and initCode is empty")
|
|
154
|
+
) {
|
|
155
|
+
throw new BaseError(
|
|
156
|
+
`${err.details} (If using 7702, be sure you include the signed authorization in the request parameters)`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
throw err;
|
|
160
|
+
});
|
|
161
|
+
}),
|
|
162
|
+
);
|
|
118
163
|
|
|
119
164
|
return {
|
|
120
|
-
preparedCallIds:
|
|
165
|
+
preparedCallIds: hashes.map((hash) =>
|
|
166
|
+
Value.Encode(TypeCallId, {
|
|
167
|
+
chainId: toHex(client.chain.id),
|
|
168
|
+
hash,
|
|
169
|
+
}),
|
|
170
|
+
),
|
|
121
171
|
};
|
|
122
172
|
}
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import type { SmartAccountClient, SmartContractAccount } from "@aa-sdk/core";
|
|
2
2
|
import {
|
|
3
3
|
concatHex,
|
|
4
|
-
|
|
4
|
+
numberToHex,
|
|
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 { PreparedCall_Authorization } from "../../schemas.js";
|
|
12
|
+
import type { Eip7702AuthCapability } from "../../capabilities/eip7702Auth.ts";
|
|
13
|
+
import type { Static } from "@sinclair/typebox";
|
|
14
|
+
import { InvalidRequestError } from "ox/RpcResponse";
|
|
10
15
|
|
|
11
|
-
export const
|
|
16
|
+
export const createAuthorizationRequest = async (
|
|
12
17
|
client: SmartAccountClient<
|
|
13
18
|
Transport,
|
|
14
19
|
Chain,
|
|
@@ -17,42 +22,95 @@ export const createAuthorization = async (
|
|
|
17
22
|
WalletServerViemRpcSchema
|
|
18
23
|
>,
|
|
19
24
|
params: { address: Address; delegation: Address },
|
|
20
|
-
): Promise<
|
|
25
|
+
): Promise<Static<typeof PreparedCall_Authorization> | undefined> => {
|
|
21
26
|
const expectedCode = concatHex(["0xef0100", params.delegation]);
|
|
22
27
|
const code = (await client.getCode({ address: params.address })) ?? "0x";
|
|
23
28
|
if (code.toLowerCase() === expectedCode.toLowerCase()) {
|
|
24
29
|
return undefined; // Already authorized.
|
|
25
30
|
}
|
|
26
|
-
|
|
27
|
-
chainId: client.chain.id,
|
|
31
|
+
const data = {
|
|
28
32
|
address: params.delegation,
|
|
29
|
-
nonce:
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
nonce: numberToHex(
|
|
34
|
+
await client.getTransactionCount({
|
|
35
|
+
address: params.address,
|
|
36
|
+
}),
|
|
37
|
+
),
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
type: "authorization" as const,
|
|
41
|
+
data,
|
|
42
|
+
chainId: numberToHex(client.chain.id),
|
|
43
|
+
signatureRequest: {
|
|
44
|
+
type: "eip7702Auth" as const,
|
|
45
|
+
},
|
|
32
46
|
};
|
|
33
47
|
};
|
|
34
48
|
|
|
35
|
-
|
|
49
|
+
export const EIP_7702_ACCOUNT_TYPE = ["ModularAccountV2"] as const;
|
|
50
|
+
|
|
51
|
+
type Supported7702AccountType = (typeof EIP_7702_ACCOUNT_TYPE)[number];
|
|
36
52
|
|
|
37
|
-
const
|
|
53
|
+
const Eip7702AccountTypeToDelegationAddress = {
|
|
54
|
+
ModularAccountV2: "0x69007702764179f14F51cdce752f4f775d74E139",
|
|
55
|
+
} as const satisfies Record<Supported7702AccountType, Address>;
|
|
56
|
+
|
|
57
|
+
const DelegationAddressToAccountType: Record<
|
|
38
58
|
Address,
|
|
39
59
|
Supported7702AccountType
|
|
40
|
-
> =
|
|
41
|
-
|
|
60
|
+
> = Object.fromEntries(
|
|
61
|
+
Object.entries(Eip7702AccountTypeToDelegationAddress).map(([key, value]) => [
|
|
62
|
+
value,
|
|
63
|
+
key,
|
|
64
|
+
]),
|
|
65
|
+
) as Record<Address, Supported7702AccountType>;
|
|
66
|
+
|
|
67
|
+
export const SUPPORTED_DELEGATION_ADDRESSES = Object.values(
|
|
68
|
+
Eip7702AccountTypeToDelegationAddress,
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
export const isSupportedDelegationAddress7702 = (address: Address): boolean => {
|
|
72
|
+
return (SUPPORTED_DELEGATION_ADDRESSES as Address[]).includes(address);
|
|
42
73
|
};
|
|
43
74
|
|
|
44
|
-
export const
|
|
75
|
+
export const getAccountTypeForDelegationAddress7702 = (
|
|
45
76
|
address: Address,
|
|
46
77
|
): Supported7702AccountType | undefined => {
|
|
47
|
-
return
|
|
78
|
+
return DelegationAddressToAccountType[address];
|
|
48
79
|
};
|
|
49
80
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
)
|
|
81
|
+
const getDelegationAddressForAccountType7702 = (
|
|
82
|
+
accountType: Supported7702AccountType,
|
|
83
|
+
): (typeof SUPPORTED_DELEGATION_ADDRESSES)[number] => {
|
|
84
|
+
return Eip7702AccountTypeToDelegationAddress[accountType];
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
const DEFAULT_7702_DELEGATION_ADDR =
|
|
88
|
+
Eip7702AccountTypeToDelegationAddress["ModularAccountV2"];
|
|
53
89
|
|
|
54
|
-
export const
|
|
55
|
-
|
|
56
|
-
)
|
|
57
|
-
return
|
|
90
|
+
export const parseDelegation = (
|
|
91
|
+
eip7702AuthCapability: Static<typeof Eip7702AuthCapability>,
|
|
92
|
+
) => {
|
|
93
|
+
return eip7702AuthCapability === true
|
|
94
|
+
? DEFAULT_7702_DELEGATION_ADDR
|
|
95
|
+
: isAddress(eip7702AuthCapability.delegation)
|
|
96
|
+
? eip7702AuthCapability.delegation
|
|
97
|
+
: getDelegationAddressForAccountType7702(
|
|
98
|
+
eip7702AuthCapability.delegation,
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export const assertValid7702AccountAddress = (
|
|
103
|
+
fromAddress: Address,
|
|
104
|
+
eip7702AuthCapability: Static<typeof Eip7702AuthCapability> | undefined,
|
|
105
|
+
) => {
|
|
106
|
+
if (
|
|
107
|
+
eip7702AuthCapability &&
|
|
108
|
+
typeof eip7702AuthCapability === "object" &&
|
|
109
|
+
"account" in eip7702AuthCapability &&
|
|
110
|
+
eip7702AuthCapability?.account !== fromAddress
|
|
111
|
+
) {
|
|
112
|
+
throw new InvalidRequestError({
|
|
113
|
+
message: `EIP-7702 delegation account ${eip7702AuthCapability.account} must match 'from' address ${fromAddress}.`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
58
116
|
};
|
|
@@ -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 {
|
|
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 =
|
|
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.
|
|
63
|
+
params.permissions,
|
|
64
64
|
ci,
|
|
65
65
|
params.delegation,
|
|
66
66
|
);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Value } from "@sinclair/typebox/value";
|
|
2
|
+
import type { Static, StaticDecode } from "@sinclair/typebox";
|
|
3
|
+
import { TypeEcdsaSig } from "../../schemas.js";
|
|
4
|
+
import { assertNever } from "../../utils.js";
|
|
5
|
+
|
|
6
|
+
export const decodeSignature = (
|
|
7
|
+
signature: Static<typeof TypeEcdsaSig>["signature"],
|
|
8
|
+
): StaticDecode<typeof TypeEcdsaSig>["signature"] => {
|
|
9
|
+
switch (signature.type) {
|
|
10
|
+
case "ecdsa":
|
|
11
|
+
case "secp256k1":
|
|
12
|
+
return Value.Decode(TypeEcdsaSig, { signature } satisfies Static<
|
|
13
|
+
typeof TypeEcdsaSig
|
|
14
|
+
>).signature;
|
|
15
|
+
default:
|
|
16
|
+
return assertNever(signature, "Unexpected signature type");
|
|
17
|
+
}
|
|
18
|
+
};
|
|
@@ -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 {
|
|
6
|
+
import { getAccountTypeForDelegationAddress7702 } from "./7702.js";
|
|
7
|
+
import { PermissionsCapability } from "../../capabilities/permissions/index.js";
|
|
8
8
|
|
|
9
9
|
export function parsePermissionsContext(
|
|
10
|
-
|
|
11
|
-
parsedCi
|
|
10
|
+
permissions?: StaticDecode<typeof PermissionsCapability>,
|
|
11
|
+
parsedCi?: StaticDecode<typeof TypeSerializedInitcode> | undefined,
|
|
12
12
|
delegation7702?: Address,
|
|
13
13
|
) {
|
|
14
|
-
if (!
|
|
14
|
+
if (!permissions) {
|
|
15
15
|
return undefined;
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
if ("sessionId" in
|
|
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
|
|
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
|
-
|
|
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(
|
|
40
|
+
const context = decodePermissionsContext(permissions);
|
|
41
41
|
|
|
42
42
|
if (context?.contextVersion === "REMOTE_MODE_DEFERRED_ACTION") {
|
|
43
43
|
throw new InvalidRequestError({
|