@account-kit/smart-contracts 4.41.0 → 4.42.0
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/src/ma-v2/account/common/modularAccountV2Base.d.ts +17 -3
- package/dist/esm/src/ma-v2/account/common/modularAccountV2Base.js +23 -5
- package/dist/esm/src/ma-v2/account/common/modularAccountV2Base.js.map +1 -1
- package/dist/esm/src/ma-v2/account/modularAccountV2.d.ts +15 -1
- package/dist/esm/src/ma-v2/account/modularAccountV2.js +67 -7
- package/dist/esm/src/ma-v2/account/modularAccountV2.js.map +1 -1
- package/dist/esm/src/ma-v2/client/client.d.ts +15 -7
- package/dist/esm/src/ma-v2/client/client.js +23 -7
- package/dist/esm/src/ma-v2/client/client.js.map +1 -1
- package/dist/esm/src/ma-v2/errors.d.ts +22 -0
- package/dist/esm/src/ma-v2/errors.js +44 -0
- package/dist/esm/src/ma-v2/errors.js.map +1 -0
- package/dist/esm/src/ma-v2/index.d.ts +1 -0
- package/dist/esm/src/ma-v2/index.js +1 -0
- package/dist/esm/src/ma-v2/index.js.map +1 -1
- package/dist/esm/src/ma-v2/modules/webauthn-validation/signingMethods.d.ts +36 -0
- package/dist/esm/src/ma-v2/modules/webauthn-validation/signingMethods.js +119 -0
- package/dist/esm/src/ma-v2/modules/webauthn-validation/signingMethods.js.map +1 -0
- package/dist/types/src/ma-v2/account/common/modularAccountV2Base.d.ts +17 -3
- package/dist/types/src/ma-v2/account/common/modularAccountV2Base.d.ts.map +1 -1
- package/dist/types/src/ma-v2/account/modularAccountV2.d.ts +15 -1
- package/dist/types/src/ma-v2/account/modularAccountV2.d.ts.map +1 -1
- package/dist/types/src/ma-v2/client/client.d.ts +15 -7
- package/dist/types/src/ma-v2/client/client.d.ts.map +1 -1
- package/dist/types/src/ma-v2/errors.d.ts +23 -0
- package/dist/types/src/ma-v2/errors.d.ts.map +1 -0
- package/dist/types/src/ma-v2/index.d.ts +1 -0
- package/dist/types/src/ma-v2/index.d.ts.map +1 -1
- package/dist/types/src/ma-v2/modules/webauthn-validation/signingMethods.d.ts +37 -0
- package/dist/types/src/ma-v2/modules/webauthn-validation/signingMethods.d.ts.map +1 -0
- package/package.json +5 -5
- package/src/ma-v2/account/common/modularAccountV2Base.ts +71 -8
- package/src/ma-v2/account/modularAccountV2.ts +115 -9
- package/src/ma-v2/client/client.ts +73 -17
- package/src/ma-v2/errors.ts +33 -0
- package/src/ma-v2/index.ts +1 -0
- package/src/ma-v2/modules/webauthn-validation/signingMethods.ts +158 -0
|
@@ -7,6 +7,8 @@ import {
|
|
|
7
7
|
getEntryPoint,
|
|
8
8
|
EntityIdOverrideError,
|
|
9
9
|
InvalidModularAccountV2Mode,
|
|
10
|
+
createBundlerClient,
|
|
11
|
+
getAccountAddress,
|
|
10
12
|
} from "@aa-sdk/core";
|
|
11
13
|
import {
|
|
12
14
|
concatHex,
|
|
@@ -25,9 +27,17 @@ import {
|
|
|
25
27
|
type SignerEntity,
|
|
26
28
|
type ModularAccountV2,
|
|
27
29
|
createMAv2Base,
|
|
30
|
+
type WebauthnModularAccountV2,
|
|
28
31
|
} from "./common/modularAccountV2Base.js";
|
|
29
32
|
import { DEFAULT_OWNER_ENTITY_ID } from "../utils.js";
|
|
30
33
|
import { predictModularAccountV2Address } from "./predictAddress.js";
|
|
34
|
+
import type { ToWebAuthnAccountParameters } from "viem/account-abstraction";
|
|
35
|
+
import { parsePublicKey } from "webauthn-p256";
|
|
36
|
+
import {
|
|
37
|
+
SignerRequiredFor7702Error,
|
|
38
|
+
SignerRequiredForDefaultError,
|
|
39
|
+
WebauthnCredentialsRequiredError,
|
|
40
|
+
} from "../errors.js";
|
|
31
41
|
|
|
32
42
|
export type CreateModularAccountV2Params<
|
|
33
43
|
TTransport extends Transport = Transport,
|
|
@@ -54,6 +64,24 @@ export type CreateModularAccountV2Params<
|
|
|
54
64
|
}
|
|
55
65
|
);
|
|
56
66
|
|
|
67
|
+
export type CreateWebauthnModularAccountV2Params<
|
|
68
|
+
TTransport extends Transport = Transport,
|
|
69
|
+
> = Pick<
|
|
70
|
+
ToSmartContractAccountParams<"ModularAccountV2", TTransport, Chain, "0.7.0">,
|
|
71
|
+
"transport" | "chain" | "accountAddress"
|
|
72
|
+
> & {
|
|
73
|
+
mode: "webauthn";
|
|
74
|
+
credential: ToWebAuthnAccountParameters["credential"];
|
|
75
|
+
getFn?: ToWebAuthnAccountParameters["getFn"] | undefined;
|
|
76
|
+
rpId?: ToWebAuthnAccountParameters["rpId"] | undefined;
|
|
77
|
+
entryPoint?: EntryPointDef<"0.7.0", Chain>;
|
|
78
|
+
deferredAction?: Hex;
|
|
79
|
+
signerEntity?: SignerEntity;
|
|
80
|
+
salt?: bigint;
|
|
81
|
+
factoryAddress?: Address;
|
|
82
|
+
initCode?: Hex;
|
|
83
|
+
};
|
|
84
|
+
|
|
57
85
|
export async function createModularAccountV2<
|
|
58
86
|
TTransport extends Transport = Transport,
|
|
59
87
|
TSigner extends SmartAccountSigner = SmartAccountSigner,
|
|
@@ -61,6 +89,12 @@ export async function createModularAccountV2<
|
|
|
61
89
|
config: CreateModularAccountV2Params<TTransport, TSigner>,
|
|
62
90
|
): Promise<ModularAccountV2<TSigner>>;
|
|
63
91
|
|
|
92
|
+
export async function createModularAccountV2<
|
|
93
|
+
TTransport extends Transport = Transport,
|
|
94
|
+
>(
|
|
95
|
+
config: CreateWebauthnModularAccountV2Params<TTransport>,
|
|
96
|
+
): Promise<WebauthnModularAccountV2>;
|
|
97
|
+
|
|
64
98
|
/**
|
|
65
99
|
* Creates a ModularAccount V2 account, with the mode depending on the provided "mode" field.
|
|
66
100
|
* Possible modes include: "default", which is SMA Bytecode, and "7702", which is SMA 7702.
|
|
@@ -90,16 +124,20 @@ export async function createModularAccountV2<
|
|
|
90
124
|
* });
|
|
91
125
|
* ```
|
|
92
126
|
*
|
|
93
|
-
* @param {CreateModularAccountV2Params} config Configuration parameters for creating a Modular Account V2.
|
|
94
|
-
* @returns {Promise<ModularAccountV2>} A promise that resolves to an `ModularAccountV2` providing methods for nonce retrieval, transaction execution, and more.
|
|
127
|
+
* @param {CreateModularAccountV2Params | CreateWebauthnModularAccountV2Params} config Configuration parameters for creating a Modular Account V2.
|
|
128
|
+
* @returns {Promise<ModularAccountV2 | WebauthnModularAccountV2>} A promise that resolves to an `ModularAccountV2` providing methods for nonce retrieval, transaction execution, and more.
|
|
95
129
|
*/
|
|
96
|
-
export async function createModularAccountV2
|
|
97
|
-
|
|
98
|
-
|
|
130
|
+
export async function createModularAccountV2<
|
|
131
|
+
TTransport extends Transport = Transport,
|
|
132
|
+
TSigner extends SmartAccountSigner = SmartAccountSigner,
|
|
133
|
+
>(
|
|
134
|
+
config:
|
|
135
|
+
| CreateModularAccountV2Params<TTransport, TSigner>
|
|
136
|
+
| CreateWebauthnModularAccountV2Params<TTransport>,
|
|
137
|
+
): Promise<ModularAccountV2<TSigner> | WebauthnModularAccountV2> {
|
|
99
138
|
const {
|
|
100
139
|
transport,
|
|
101
140
|
chain,
|
|
102
|
-
signer,
|
|
103
141
|
accountAddress: _accountAddress,
|
|
104
142
|
entryPoint = getEntryPoint(chain, { version: "0.7.0" }),
|
|
105
143
|
signerEntity = {
|
|
@@ -110,12 +148,63 @@ export async function createModularAccountV2(
|
|
|
110
148
|
deferredAction,
|
|
111
149
|
} = config;
|
|
112
150
|
|
|
151
|
+
const signer = "signer" in config ? config.signer : undefined;
|
|
152
|
+
|
|
153
|
+
const credential = "credential" in config ? config.credential : undefined;
|
|
154
|
+
|
|
155
|
+
const getFn = "getFn" in config ? config.getFn : undefined;
|
|
156
|
+
|
|
157
|
+
const rpId = "rpId" in config ? config.rpId : undefined;
|
|
158
|
+
|
|
159
|
+
const client = createBundlerClient({
|
|
160
|
+
transport,
|
|
161
|
+
chain,
|
|
162
|
+
});
|
|
163
|
+
|
|
113
164
|
const accountFunctions = await (async () => {
|
|
114
165
|
switch (config.mode) {
|
|
166
|
+
case "webauthn": {
|
|
167
|
+
if (!credential) throw new WebauthnCredentialsRequiredError();
|
|
168
|
+
const publicKey = credential.publicKey;
|
|
169
|
+
const { x, y } = parsePublicKey(publicKey);
|
|
170
|
+
const {
|
|
171
|
+
salt = 0n,
|
|
172
|
+
factoryAddress = getDefaultMAV2FactoryAddress(chain),
|
|
173
|
+
initCode,
|
|
174
|
+
} = config;
|
|
175
|
+
|
|
176
|
+
const getAccountInitCode = async () => {
|
|
177
|
+
if (initCode) {
|
|
178
|
+
return initCode;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return concatHex([
|
|
182
|
+
factoryAddress,
|
|
183
|
+
encodeFunctionData({
|
|
184
|
+
abi: accountFactoryAbi,
|
|
185
|
+
functionName: "createWebAuthnAccount",
|
|
186
|
+
args: [x, y, salt, entityId],
|
|
187
|
+
}),
|
|
188
|
+
]);
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
const accountAddress = await getAccountAddress({
|
|
192
|
+
client,
|
|
193
|
+
entryPoint,
|
|
194
|
+
accountAddress: _accountAddress,
|
|
195
|
+
getAccountInitCode,
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
return {
|
|
199
|
+
getAccountInitCode,
|
|
200
|
+
accountAddress,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
115
203
|
case "7702": {
|
|
116
204
|
const getAccountInitCode = async (): Promise<Hex> => {
|
|
117
205
|
return "0x";
|
|
118
206
|
};
|
|
207
|
+
if (!signer) throw new SignerRequiredFor7702Error();
|
|
119
208
|
const signerAddress = await signer.getAddress();
|
|
120
209
|
const accountAddress = _accountAddress ?? signerAddress;
|
|
121
210
|
if (
|
|
@@ -138,6 +227,7 @@ export async function createModularAccountV2(
|
|
|
138
227
|
}
|
|
139
228
|
case "default":
|
|
140
229
|
case undefined: {
|
|
230
|
+
if (!signer) throw new SignerRequiredForDefaultError();
|
|
141
231
|
const {
|
|
142
232
|
salt = 0n,
|
|
143
233
|
factoryAddress = getDefaultMAV2FactoryAddress(chain),
|
|
@@ -157,7 +247,7 @@ export async function createModularAccountV2(
|
|
|
157
247
|
encodeFunctionData({
|
|
158
248
|
abi: accountFactoryAbi,
|
|
159
249
|
functionName: "createSemiModularAccount",
|
|
160
|
-
args: [
|
|
250
|
+
args: [await signer.getAddress(), salt],
|
|
161
251
|
}),
|
|
162
252
|
]);
|
|
163
253
|
};
|
|
@@ -182,8 +272,24 @@ export async function createModularAccountV2(
|
|
|
182
272
|
}
|
|
183
273
|
})();
|
|
184
274
|
|
|
185
|
-
|
|
186
|
-
|
|
275
|
+
if (!signer) {
|
|
276
|
+
if (!credential) throw new WebauthnCredentialsRequiredError();
|
|
277
|
+
return await createMAv2Base({
|
|
278
|
+
source: "ModularAccountV2", // TO DO: remove need to pass in source?
|
|
279
|
+
transport,
|
|
280
|
+
chain,
|
|
281
|
+
entryPoint,
|
|
282
|
+
signerEntity,
|
|
283
|
+
deferredAction,
|
|
284
|
+
credential,
|
|
285
|
+
getFn,
|
|
286
|
+
rpId,
|
|
287
|
+
...accountFunctions,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
return await createMAv2Base({
|
|
292
|
+
source: "ModularAccountV2", // TO DO: remove need to pass in source?
|
|
187
293
|
transport,
|
|
188
294
|
chain,
|
|
189
295
|
signer,
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type SmartAccountClient,
|
|
3
|
-
type SmartAccountSigner,
|
|
4
|
-
type SmartAccountClientConfig,
|
|
5
|
-
type NotType,
|
|
6
2
|
createSmartAccountClient,
|
|
7
3
|
default7702GasEstimator,
|
|
8
4
|
default7702UserOpSigner,
|
|
5
|
+
webauthnGasEstimator,
|
|
6
|
+
type SmartAccountClient,
|
|
7
|
+
type SmartAccountClientConfig,
|
|
8
|
+
type SmartAccountSigner,
|
|
9
9
|
} from "@aa-sdk/core";
|
|
10
10
|
import { type Chain, type Transport } from "viem";
|
|
11
11
|
|
|
12
12
|
import {
|
|
13
13
|
createModularAccountV2,
|
|
14
14
|
type CreateModularAccountV2Params,
|
|
15
|
+
type CreateWebauthnModularAccountV2Params,
|
|
15
16
|
} from "../account/modularAccountV2.js";
|
|
16
17
|
|
|
17
18
|
import {
|
|
@@ -23,24 +24,54 @@ import {
|
|
|
23
24
|
} from "@account-kit/infra";
|
|
24
25
|
import type { LightAccount } from "../../light-account/accounts/account.js";
|
|
25
26
|
|
|
26
|
-
import type {
|
|
27
|
+
import type { ToWebAuthnAccountParameters } from "viem/account-abstraction";
|
|
28
|
+
import type {
|
|
29
|
+
ModularAccountV2,
|
|
30
|
+
WebauthnModularAccountV2,
|
|
31
|
+
} from "../account/common/modularAccountV2Base.js";
|
|
27
32
|
|
|
28
33
|
export type ModularAccountV2Client<
|
|
29
34
|
TSigner extends SmartAccountSigner = SmartAccountSigner,
|
|
30
35
|
TChain extends Chain = Chain,
|
|
31
36
|
TTransport extends Transport | AlchemyTransport = Transport,
|
|
32
|
-
> =
|
|
37
|
+
> = TTransport extends AlchemyTransport
|
|
38
|
+
? AlchemySmartAccountClient<TChain, ModularAccountV2<TSigner>>
|
|
39
|
+
: SmartAccountClient<TTransport, TChain, ModularAccountV2<TSigner>>;
|
|
40
|
+
|
|
41
|
+
export type WebauthnModularAccountV2Client<
|
|
42
|
+
TChain extends Chain = Chain,
|
|
43
|
+
TTransport extends Transport | AlchemyTransport = Transport,
|
|
44
|
+
> = TTransport extends AlchemyTransport
|
|
45
|
+
? AlchemySmartAccountClient<TChain, WebauthnModularAccountV2>
|
|
46
|
+
: SmartAccountClient<TTransport, TChain, WebauthnModularAccountV2>;
|
|
33
47
|
|
|
34
48
|
export type CreateModularAccountV2ClientParams<
|
|
35
|
-
TTransport extends Transport = Transport,
|
|
49
|
+
TTransport extends Transport | AlchemyTransport = Transport,
|
|
36
50
|
TChain extends Chain = Chain,
|
|
37
51
|
TSigner extends SmartAccountSigner = SmartAccountSigner,
|
|
38
52
|
> = CreateModularAccountV2Params<TTransport, TSigner> &
|
|
39
53
|
Omit<
|
|
40
|
-
|
|
54
|
+
TTransport extends AlchemyTransport
|
|
55
|
+
? AlchemySmartAccountClientConfig<TChain>
|
|
56
|
+
: SmartAccountClientConfig<TTransport, TChain>,
|
|
41
57
|
"transport" | "account" | "chain"
|
|
42
58
|
>;
|
|
43
59
|
|
|
60
|
+
export type CreateWebauthnModularAccountV2ClientParams<
|
|
61
|
+
TTransport extends Transport | AlchemyTransport = Transport,
|
|
62
|
+
TChain extends Chain = Chain,
|
|
63
|
+
> = CreateWebauthnModularAccountV2Params<TTransport> &
|
|
64
|
+
Omit<
|
|
65
|
+
TTransport extends AlchemyTransport
|
|
66
|
+
? AlchemySmartAccountClientConfig<TChain>
|
|
67
|
+
: SmartAccountClientConfig<TTransport, TChain>,
|
|
68
|
+
"transport" | "account" | "chain"
|
|
69
|
+
> & {
|
|
70
|
+
credential: ToWebAuthnAccountParameters["credential"];
|
|
71
|
+
getFn?: ToWebAuthnAccountParameters["getFn"];
|
|
72
|
+
rpId?: ToWebAuthnAccountParameters["rpId"];
|
|
73
|
+
};
|
|
74
|
+
|
|
44
75
|
export type CreateModularAccountV2AlchemyClientParams<
|
|
45
76
|
TTransport extends Transport = Transport,
|
|
46
77
|
TChain extends Chain = Chain,
|
|
@@ -70,10 +101,15 @@ export function createModularAccountV2Client<
|
|
|
70
101
|
TChain extends Chain = Chain,
|
|
71
102
|
TSigner extends SmartAccountSigner = SmartAccountSigner,
|
|
72
103
|
>(
|
|
73
|
-
args: CreateModularAccountV2ClientParams<TTransport, TChain, TSigner
|
|
74
|
-
|
|
75
|
-
): Promise<ModularAccountV2Client<TSigner, TChain>>;
|
|
104
|
+
args: CreateModularAccountV2ClientParams<TTransport, TChain, TSigner>,
|
|
105
|
+
): Promise<ModularAccountV2Client<TSigner, TChain, TTransport>>;
|
|
76
106
|
|
|
107
|
+
export function createModularAccountV2Client<
|
|
108
|
+
TTransport extends Transport = Transport,
|
|
109
|
+
TChain extends Chain = Chain,
|
|
110
|
+
>(
|
|
111
|
+
args: CreateWebauthnModularAccountV2ClientParams<TTransport, TChain>,
|
|
112
|
+
): Promise<WebauthnModularAccountV2Client<TChain, TTransport>>;
|
|
77
113
|
/**
|
|
78
114
|
* Creates a Modular Account V2 client using the provided configuration parameters.
|
|
79
115
|
*
|
|
@@ -108,19 +144,39 @@ export function createModularAccountV2Client<
|
|
|
108
144
|
export async function createModularAccountV2Client(
|
|
109
145
|
config:
|
|
110
146
|
| CreateModularAccountV2ClientParams
|
|
147
|
+
| CreateWebauthnModularAccountV2ClientParams
|
|
111
148
|
| CreateModularAccountV2AlchemyClientParams,
|
|
112
149
|
): Promise<SmartAccountClient | AlchemySmartAccountClient> {
|
|
113
150
|
const { transport, chain } = config;
|
|
114
151
|
|
|
115
|
-
|
|
152
|
+
let account;
|
|
153
|
+
|
|
154
|
+
if (config.mode === "webauthn") {
|
|
155
|
+
account = await createModularAccountV2(
|
|
156
|
+
config as CreateWebauthnModularAccountV2Params<Transport>,
|
|
157
|
+
);
|
|
158
|
+
} else {
|
|
159
|
+
account = await createModularAccountV2(
|
|
160
|
+
config as CreateModularAccountV2Params,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
116
163
|
|
|
117
|
-
const middlewareToAppend =
|
|
118
|
-
config.mode
|
|
119
|
-
|
|
164
|
+
const middlewareToAppend = await (async () => {
|
|
165
|
+
switch (config.mode) {
|
|
166
|
+
case "7702":
|
|
167
|
+
return {
|
|
120
168
|
gasEstimator: default7702GasEstimator(config.gasEstimator),
|
|
121
169
|
signUserOperation: default7702UserOpSigner(config.signUserOperation),
|
|
122
|
-
}
|
|
123
|
-
:
|
|
170
|
+
};
|
|
171
|
+
case "webauthn":
|
|
172
|
+
return {
|
|
173
|
+
gasEstimator: webauthnGasEstimator(config.gasEstimator),
|
|
174
|
+
};
|
|
175
|
+
case "default":
|
|
176
|
+
default:
|
|
177
|
+
return {};
|
|
178
|
+
}
|
|
179
|
+
})();
|
|
124
180
|
|
|
125
181
|
if (isAlchemyTransport(transport, chain)) {
|
|
126
182
|
return createAlchemySmartAccountClient({
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { BaseError } from "@aa-sdk/core";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Error when Webauthn credentials are not passed to Webauthn Modular Account V2
|
|
5
|
+
*/
|
|
6
|
+
export class WebauthnCredentialsRequiredError extends BaseError {
|
|
7
|
+
override name = "WebauthnCredentialsRequiredError";
|
|
8
|
+
constructor() {
|
|
9
|
+
super(
|
|
10
|
+
"Webauthn credentials are required to create a Webauthn Modular Account V2",
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Error when a signer is not passed to 7702 version of Modular Account V2
|
|
17
|
+
*/
|
|
18
|
+
export class SignerRequiredFor7702Error extends BaseError {
|
|
19
|
+
override name = "SignerRequiredFor7702Error";
|
|
20
|
+
constructor() {
|
|
21
|
+
super("A signer is required to create a 7702 Modular Account V2");
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Error when a signer is not passed to default Modular Account V2
|
|
27
|
+
*/
|
|
28
|
+
export class SignerRequiredForDefaultError extends BaseError {
|
|
29
|
+
override name = "SignerRequiredForDefaultError";
|
|
30
|
+
constructor() {
|
|
31
|
+
super("A signer is required to create a default Modular Account V2");
|
|
32
|
+
}
|
|
33
|
+
}
|
package/src/ma-v2/index.ts
CHANGED
|
@@ -46,3 +46,4 @@ export { SingleSignerValidationModule } from "./modules/single-signer-validation
|
|
|
46
46
|
export { timeRangeModuleAbi } from "./modules/time-range-module/abis/timeRangeModuleAbi.js";
|
|
47
47
|
export { TimeRangeModule } from "./modules/time-range-module/module.js";
|
|
48
48
|
export { webauthnValidationModuleAbi } from "./modules/webauthn-validation/abis/webauthnValidationAbi.js";
|
|
49
|
+
export { WebAuthnValidationModule } from "./modules/webauthn-validation/module.js";
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import * as WebAuthnP256 from "ox/WebAuthnP256";
|
|
2
|
+
import {
|
|
3
|
+
type Address,
|
|
4
|
+
type Chain,
|
|
5
|
+
concatHex,
|
|
6
|
+
encodeAbiParameters,
|
|
7
|
+
hashMessage,
|
|
8
|
+
hashTypedData,
|
|
9
|
+
type Hex,
|
|
10
|
+
type SignableMessage,
|
|
11
|
+
type TypedData,
|
|
12
|
+
type TypedDataDefinition,
|
|
13
|
+
} from "viem";
|
|
14
|
+
import { type ToWebAuthnAccountParameters } from "viem/account-abstraction";
|
|
15
|
+
import { pack1271Signature } from "../../utils.js";
|
|
16
|
+
import { getDefaultWebauthnValidationModuleAddress } from "../utils.js";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates an object with methods for generating a dummy signature, signing user operation hashes, signing messages, and signing typed data.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
|
|
23
|
+
* ```ts
|
|
24
|
+
* import { webauthnSigningFunctions } from "@account-kit/smart-contracts";
|
|
25
|
+
* import { LocalAccountSigner } from "@aa-sdk/core";
|
|
26
|
+
*
|
|
27
|
+
* const messageSigner = webauthnSigningFunctions(credential, getFn, rpId, chain, account.address, account.signerEntity.entityId);
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @param {ToWebAuthnAccountParameters} credential the Webauthn public key credential object
|
|
31
|
+
* @param {ToWebAuthnAccountParameters["getFn"]} getFn function to retrieve the WebAuthn credential
|
|
32
|
+
* @param {ToWebAuthnAccountParameters["rpId"]} rpId the relying party ID for the WebAuthn credential
|
|
33
|
+
* @param {Chain} chain Chain object for the signer
|
|
34
|
+
* @param {Address} accountAddress address of the smart account using this signer
|
|
35
|
+
* @param {number} entityId the entity id of the signing validation
|
|
36
|
+
* @param {Hex} deferredActionData optional deferred action data to prepend to the uo signatures
|
|
37
|
+
* @returns {object} an object with methods for signing operations and managing signatures
|
|
38
|
+
*/
|
|
39
|
+
export const webauthnSigningFunctions = (
|
|
40
|
+
credential: ToWebAuthnAccountParameters["credential"],
|
|
41
|
+
getFn: ToWebAuthnAccountParameters["getFn"],
|
|
42
|
+
rpId: ToWebAuthnAccountParameters["rpId"],
|
|
43
|
+
chain: Chain,
|
|
44
|
+
accountAddress: Address,
|
|
45
|
+
entityId: number,
|
|
46
|
+
deferredActionData?: Hex,
|
|
47
|
+
) => {
|
|
48
|
+
const { id, publicKey } = credential;
|
|
49
|
+
|
|
50
|
+
const sign = async ({ hash }: { hash: Hex }) => {
|
|
51
|
+
const { metadata, signature } = await WebAuthnP256.sign({
|
|
52
|
+
credentialId: id,
|
|
53
|
+
getFn,
|
|
54
|
+
challenge: hash,
|
|
55
|
+
rpId,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
return encodeAbiParameters(
|
|
59
|
+
[
|
|
60
|
+
{
|
|
61
|
+
name: "params",
|
|
62
|
+
type: "tuple",
|
|
63
|
+
components: [
|
|
64
|
+
{ name: "authenticatorData", type: "bytes" },
|
|
65
|
+
{ name: "clientDataJSON", type: "string" },
|
|
66
|
+
{ name: "challengeIndex", type: "uint256" },
|
|
67
|
+
{ name: "typeIndex", type: "uint256" },
|
|
68
|
+
{ name: "r", type: "uint256" },
|
|
69
|
+
{ name: "s", type: "uint256" },
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
[
|
|
74
|
+
{
|
|
75
|
+
authenticatorData: metadata.authenticatorData,
|
|
76
|
+
clientDataJSON: metadata.clientDataJSON,
|
|
77
|
+
challengeIndex: BigInt(metadata.challengeIndex),
|
|
78
|
+
typeIndex: BigInt(metadata.typeIndex),
|
|
79
|
+
r: signature.r,
|
|
80
|
+
s: signature.s,
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
id,
|
|
88
|
+
publicKey,
|
|
89
|
+
getDummySignature: (): Hex =>
|
|
90
|
+
"0xff000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000170000000000000000000000000000000000000000000000000000000000000001949fc7c88032b9fcb5f6efc7a7b8c63668eae9871b765e23123bb473ff57aa831a7c0d9276168ebcc29f2875a0239cffdf2a9cd1c2007c5c77c071db9264df1d000000000000000000000000000000000000000000000000000000000000002549960de5880e8c687434170f6476605b8fe4aeb9a28632c7995cf3ba831d97630500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008a7b2274797065223a22776562617574686e2e676574222c226368616c6c656e6765223a2273496a396e6164474850596759334b7156384f7a4a666c726275504b474f716d59576f4d57516869467773222c226f726967696e223a2268747470733a2f2f7369676e2e636f696e626173652e636f6d222c2263726f73734f726967696e223a66616c73657d00000000000000000000000000000000000000000000",
|
|
91
|
+
sign,
|
|
92
|
+
signUserOperationHash: async (uoHash: Hex): Promise<Hex> => {
|
|
93
|
+
let sig = await sign({ hash: hashMessage({ raw: uoHash }) });
|
|
94
|
+
if (deferredActionData) {
|
|
95
|
+
sig = concatHex([deferredActionData, sig]);
|
|
96
|
+
deferredActionData = undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return concatHex(["0xff", sig]);
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
async signMessage({ message }: { message: SignableMessage }): Promise<Hex> {
|
|
103
|
+
const hash = hashTypedData({
|
|
104
|
+
domain: {
|
|
105
|
+
chainId: Number(chain.id),
|
|
106
|
+
verifyingContract: getDefaultWebauthnValidationModuleAddress(chain),
|
|
107
|
+
salt: concatHex([`0x${"00".repeat(12)}`, accountAddress]),
|
|
108
|
+
},
|
|
109
|
+
types: {
|
|
110
|
+
ReplaySafeHash: [{ name: "hash", type: "bytes32" }],
|
|
111
|
+
},
|
|
112
|
+
message: {
|
|
113
|
+
hash: hashMessage(message),
|
|
114
|
+
},
|
|
115
|
+
primaryType: "ReplaySafeHash",
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
return pack1271Signature({
|
|
119
|
+
validationSignature: await sign({ hash }),
|
|
120
|
+
entityId,
|
|
121
|
+
});
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
signTypedData: async <
|
|
125
|
+
const typedData extends TypedData | Record<string, unknown>,
|
|
126
|
+
primaryType extends keyof typedData | "EIP712Domain" = keyof typedData,
|
|
127
|
+
>(
|
|
128
|
+
typedDataDefinition: TypedDataDefinition<typedData, primaryType>,
|
|
129
|
+
): Promise<Hex> => {
|
|
130
|
+
const isDeferredAction =
|
|
131
|
+
typedDataDefinition?.primaryType === "DeferredAction" &&
|
|
132
|
+
// @ts-expect-error the domain type I think changed in viem, so this is not working correctly (TODO: fix this)
|
|
133
|
+
"verifyingContract" in typedDataDefinition.domain &&
|
|
134
|
+
typedDataDefinition.domain.verifyingContract === accountAddress;
|
|
135
|
+
|
|
136
|
+
const hash = await hashTypedData({
|
|
137
|
+
domain: {
|
|
138
|
+
chainId: Number(chain.id),
|
|
139
|
+
verifyingContract: getDefaultWebauthnValidationModuleAddress(chain),
|
|
140
|
+
salt: concatHex([`0x${"00".repeat(12)}`, accountAddress]),
|
|
141
|
+
},
|
|
142
|
+
types: {
|
|
143
|
+
ReplaySafeHash: [{ name: "hash", type: "bytes32" }],
|
|
144
|
+
},
|
|
145
|
+
message: {
|
|
146
|
+
hash: hashTypedData(typedDataDefinition),
|
|
147
|
+
},
|
|
148
|
+
primaryType: "ReplaySafeHash",
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const validationSignature = await sign({ hash });
|
|
152
|
+
|
|
153
|
+
return isDeferredAction
|
|
154
|
+
? pack1271Signature({ validationSignature, entityId })
|
|
155
|
+
: validationSignature;
|
|
156
|
+
},
|
|
157
|
+
};
|
|
158
|
+
};
|