@dynamic-labs/ethereum-aa 4.11.1 → 4.12.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/CHANGELOG.md +25 -0
- package/package.cjs +1 -1
- package/package.js +1 -1
- package/package.json +10 -9
- package/src/AccountAbstractionConnector.cjs +104 -0
- package/src/AccountAbstractionConnector.d.ts +69 -0
- package/src/AccountAbstractionConnector.js +100 -0
- package/src/ZKsyncConnector.cjs +526 -0
- package/src/ZKsyncConnector.d.ts +17228 -0
- package/src/ZKsyncConnector.js +522 -0
- package/src/ZeroDevConnector.cjs +15 -38
- package/src/ZeroDevConnector.d.ts +17 -7677
- package/src/ZeroDevConnector.js +17 -40
- package/src/index.cjs +11 -0
- package/src/index.d.ts +2 -0
- package/src/index.js +10 -1
- package/src/utils/abi.cjs +88 -0
- package/src/utils/abi.d.ts +102 -0
- package/src/utils/abi.js +84 -0
- package/src/utils/index.d.ts +1 -0
- package/src/utils/isZKsyncConnector.cjs +8 -0
- package/src/utils/isZKsyncConnector.d.ts +3 -0
- package/src/utils/isZKsyncConnector.js +4 -0
- package/src/utils/zksync/deployment.cjs +97 -0
- package/src/utils/zksync/deployment.d.ts +37 -0
- package/src/utils/zksync/deployment.js +91 -0
- package/src/utils/zksync/getSalt.cjs +10 -0
- package/src/utils/zksync/getSalt.d.ts +1 -0
- package/src/utils/zksync/getSalt.js +6 -0
- package/src/utils/zksync/index.d.ts +4 -0
- package/src/utils/zksync/network.cjs +17 -0
- package/src/utils/zksync/network.d.ts +2 -0
- package/src/utils/zksync/network.js +13 -0
- package/src/utils/zksync/passkeys.cjs +41 -0
- package/src/utils/zksync/passkeys.d.ts +9 -0
- package/src/utils/zksync/passkeys.js +37 -0
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import { __awaiter } from '../_virtual/_tslib.js';
|
|
3
|
+
import { createPublicClient, http, createWalletClient, custom, publicActions, walletActions, toHex } from 'viem';
|
|
4
|
+
import { getGeneralPaymasterInput, eip712WalletActions } from 'viem/zksync';
|
|
5
|
+
import { createZksyncPasskeyClient, registerNewPasskey } from 'zksync-sso/client/passkey';
|
|
6
|
+
import { encodeModuleData } from 'zksync-sso/utils';
|
|
7
|
+
import { createZksyncSessionClient } from 'zksync-sso/client';
|
|
8
|
+
import { createZksyncEcdsaClient, zksyncSsoEcdsaWalletActions } from 'zksync-sso/client/ecdsa';
|
|
9
|
+
import { EthereumWallet, getOrMapViemChain, chainsMap, confirmationTransport } from '@dynamic-labs/ethereum-core';
|
|
10
|
+
import { parseEvmNetworks, DeferredPromise, StorageService, DynamicError } from '@dynamic-labs/utils';
|
|
11
|
+
import { AccountAbstractionConnector } from './AccountAbstractionConnector.js';
|
|
12
|
+
import './utils/logger.js';
|
|
13
|
+
import '@zerodev/sdk/accounts';
|
|
14
|
+
import '@zerodev/sdk/clients';
|
|
15
|
+
import '@zerodev/sdk/actions';
|
|
16
|
+
import '@zerodev/ecdsa-validator';
|
|
17
|
+
import '@zerodev/sdk/constants';
|
|
18
|
+
import '@zerodev/multi-chain-ecdsa-validator';
|
|
19
|
+
import '@dynamic-labs/sdk-api-core';
|
|
20
|
+
import { getSalt } from './utils/zksync/getSalt.js';
|
|
21
|
+
import { getEncodedPasskeyModuleData } from './utils/zksync/passkeys.js';
|
|
22
|
+
import { getDeploymentParameters, simulateAccountDeployment, executeAccountDeployment } from './utils/zksync/deployment.js';
|
|
23
|
+
import { ensureEoaConnectorNetwork } from './utils/zksync/network.js';
|
|
24
|
+
|
|
25
|
+
class ZKsyncConnector extends AccountAbstractionConnector {
|
|
26
|
+
constructor(props) {
|
|
27
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
28
|
+
super(props);
|
|
29
|
+
// Core wallet properties
|
|
30
|
+
this.ChainWallet = EthereumWallet;
|
|
31
|
+
this.name = 'ZKsync';
|
|
32
|
+
this.overrideKey = 'zksync';
|
|
33
|
+
// Chain configuration
|
|
34
|
+
this.connectedChain = 'EVM';
|
|
35
|
+
this.evmNetworks = [];
|
|
36
|
+
this.supportedChains = ['ETH', 'EVM'];
|
|
37
|
+
this._isSmartAccountDeployed = false;
|
|
38
|
+
this.enablePasskeys = true;
|
|
39
|
+
this.enableEIP7702Mode = false;
|
|
40
|
+
this.walletFallback = {
|
|
41
|
+
brand: {
|
|
42
|
+
alt: 'Smart Wallet',
|
|
43
|
+
spriteId: 'smartwallet',
|
|
44
|
+
},
|
|
45
|
+
name: 'ZKsync',
|
|
46
|
+
};
|
|
47
|
+
this._walletUiUtils = props.walletUiUtils;
|
|
48
|
+
this.providersConfig = (_a = props.providersConfig) !== null && _a !== void 0 ? _a : {};
|
|
49
|
+
this.chainId = (_b = props.apiProviders.zksync) === null || _b === void 0 ? void 0 : _b.defaultChainId;
|
|
50
|
+
this.evmNetworks = parseEvmNetworks(props.evmNetworks).filter((network) => network.chainId === this.chainId);
|
|
51
|
+
this.factoryAddress = (_c = props.apiProviders.zksync) === null || _c === void 0 ? void 0 : _c.factoryAddress; // Fallback if not provided
|
|
52
|
+
this.paymasterAddress = (_d = props.apiProviders.zksync) === null || _d === void 0 ? void 0 : _d.paymasterAddress; // Fallback if not provided
|
|
53
|
+
this.passkeyAddress = (_e = props.apiProviders.zksync) === null || _e === void 0 ? void 0 : _e.passkeyAddress; // Fallback if not provided
|
|
54
|
+
this.sessionKeyAddress = (_f = props.apiProviders.zksync) === null || _f === void 0 ? void 0 : _f.sessionAddress; // Fallback if not provided
|
|
55
|
+
this.saltText = (_g = props.apiProviders.zksync) === null || _g === void 0 ? void 0 : _g.salt;
|
|
56
|
+
this.enablePasskeys =
|
|
57
|
+
(_j = (_h = props.settings.sdk.accountAbstraction) === null || _h === void 0 ? void 0 : _h.enablePasskeys) !== null && _j !== void 0 ? _j : false;
|
|
58
|
+
}
|
|
59
|
+
getEnabledNetworks() {
|
|
60
|
+
return this.evmNetworks;
|
|
61
|
+
}
|
|
62
|
+
getConnectedAccounts() {
|
|
63
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
64
|
+
var _a;
|
|
65
|
+
yield ((_a = this.initializedDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
|
|
66
|
+
if (!this.smartAccountAddress) {
|
|
67
|
+
throw new Error('Smart account address is not initialized');
|
|
68
|
+
}
|
|
69
|
+
return [this.smartAccountAddress];
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
getNetwork() {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
74
|
+
var _a;
|
|
75
|
+
yield ((_a = this.initializedDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
|
|
76
|
+
if (!this.smartAccountAddress) {
|
|
77
|
+
throw new Error('Smart account address is not initialized');
|
|
78
|
+
}
|
|
79
|
+
return this.chainId;
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
getPublicClient() {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
return createPublicClient({
|
|
85
|
+
chain: getOrMapViemChain(this.evmNetworks[0]),
|
|
86
|
+
transport: http(),
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
canSponsorTransactionGas() {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
return false;
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
getAccountAbstractionProvider() {
|
|
96
|
+
return this.smartAccount;
|
|
97
|
+
}
|
|
98
|
+
getWalletClient(chainId) {
|
|
99
|
+
const smartAccountClient = this.smartAccount;
|
|
100
|
+
if (!smartAccountClient) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const transport = this.getWalletClientTransport(smartAccountClient);
|
|
104
|
+
return createWalletClient({
|
|
105
|
+
account: smartAccountClient.account,
|
|
106
|
+
chain: chainId ? chainsMap[chainId] : smartAccountClient.chain,
|
|
107
|
+
transport,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
getWalletClientTransport(smartAccountClient) {
|
|
111
|
+
return custom({
|
|
112
|
+
request: (_a) => __awaiter(this, [_a], void 0, function* ({ method, params, }) {
|
|
113
|
+
const handleRequest = () => __awaiter(this, void 0, void 0, function* () {
|
|
114
|
+
var _b;
|
|
115
|
+
switch (method) {
|
|
116
|
+
case 'personal_sign':
|
|
117
|
+
// Delegate signing to the smart account client instance
|
|
118
|
+
return smartAccountClient.signMessage({ message: params[0] });
|
|
119
|
+
case 'eth_signTypedData_v4': {
|
|
120
|
+
// Delegate typed data signing to the smart account client instance
|
|
121
|
+
// Note: ZKsync usually expects JSON string for EIP712, but viem standard passes object.
|
|
122
|
+
// The smartAccountClient's signTypedData should handle the expected format internally.
|
|
123
|
+
const signTypedDataParams = params[1]; // Assuming standard viem format
|
|
124
|
+
return smartAccountClient.signTypedData(signTypedDataParams);
|
|
125
|
+
}
|
|
126
|
+
case 'eth_sendTransaction':
|
|
127
|
+
// Delegate transaction sending to the smart account client instance.
|
|
128
|
+
// This ensures deployment checks, paymaster logic, etc., are handled.
|
|
129
|
+
return smartAccountClient.sendTransaction(params[0]);
|
|
130
|
+
case 'eth_accounts':
|
|
131
|
+
case 'eth_requestAccounts':
|
|
132
|
+
// Return the smart account address
|
|
133
|
+
return ((_b = smartAccountClient.account) === null || _b === void 0 ? void 0 : _b.address)
|
|
134
|
+
? [smartAccountClient.account.address]
|
|
135
|
+
: [];
|
|
136
|
+
case 'eth_chainId': {
|
|
137
|
+
// Return chainId from the smart account client
|
|
138
|
+
const chainId = yield smartAccountClient.getChainId();
|
|
139
|
+
return toHex(chainId);
|
|
140
|
+
}
|
|
141
|
+
default: {
|
|
142
|
+
// For other read-only methods, delegate to a basic public client transport.
|
|
143
|
+
// Avoid creating a new client/transport on every call if possible,
|
|
144
|
+
// but for simplicity here, we create it transiently.
|
|
145
|
+
// Consider caching the provided client if performance becomes an issue.
|
|
146
|
+
return smartAccountClient.request({ method, params });
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
// The internal confirmationTransport used by smartAccountClient via its 'owner'
|
|
151
|
+
// should handle the UI prompts. We don't need to add extra prompts here.
|
|
152
|
+
return handleRequest();
|
|
153
|
+
}),
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
getTransport(provider) {
|
|
157
|
+
const transport = confirmationTransport({
|
|
158
|
+
getAccounts: () => __awaiter(this, void 0, void 0, function* () { return [provider.account.address]; }),
|
|
159
|
+
onPersonalSign: (_a) => __awaiter(this, [_a], void 0, function* ({ message }) {
|
|
160
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
161
|
+
if (!this._isSmartAccountDeployed) {
|
|
162
|
+
yield this.deploySmartAccount({
|
|
163
|
+
withPaymaster: true,
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
167
|
+
return provider.signMessage({
|
|
168
|
+
message,
|
|
169
|
+
});
|
|
170
|
+
}),
|
|
171
|
+
onSignTypedData: (_b) => __awaiter(this, [_b], void 0, function* ({ message }) {
|
|
172
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
173
|
+
const signTypedData = JSON.parse(message);
|
|
174
|
+
if (!this._isSmartAccountDeployed) {
|
|
175
|
+
yield this.deploySmartAccount({
|
|
176
|
+
withPaymaster: true,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
180
|
+
return provider.signTypedData({
|
|
181
|
+
domain: signTypedData.domain,
|
|
182
|
+
message: signTypedData.message,
|
|
183
|
+
primaryType: signTypedData.primaryType,
|
|
184
|
+
types: signTypedData.types,
|
|
185
|
+
});
|
|
186
|
+
}),
|
|
187
|
+
provider: provider.extend(publicActions),
|
|
188
|
+
transport: custom(provider, this.providersConfig.httpTransportConfig),
|
|
189
|
+
walletConnector: this,
|
|
190
|
+
walletUiUtils: this._walletUiUtils,
|
|
191
|
+
});
|
|
192
|
+
return transport;
|
|
193
|
+
}
|
|
194
|
+
createEcdsaClient(eoaConnector) {
|
|
195
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
196
|
+
const eoaSigner = yield (eoaConnector === null || eoaConnector === void 0 ? void 0 : eoaConnector.getSigner());
|
|
197
|
+
if (!eoaSigner) {
|
|
198
|
+
throw new Error('EOA wallet client not found');
|
|
199
|
+
}
|
|
200
|
+
if (!this.smartAccountAddress) {
|
|
201
|
+
throw new Error('Smart account address is not initialized');
|
|
202
|
+
}
|
|
203
|
+
const transport = this.getTransport(eoaSigner);
|
|
204
|
+
const ownerWithTransport = createWalletClient(Object.assign(Object.assign({}, eoaSigner), { transport }));
|
|
205
|
+
const walletClient = yield createZksyncEcdsaClient({
|
|
206
|
+
address: this.smartAccountAddress,
|
|
207
|
+
chain: getOrMapViemChain(this.evmNetworks[0]),
|
|
208
|
+
contracts: {
|
|
209
|
+
accountFactory: this.factoryAddress,
|
|
210
|
+
session: this.sessionKeyAddress,
|
|
211
|
+
},
|
|
212
|
+
owner: ownerWithTransport,
|
|
213
|
+
transport: custom(ownerWithTransport),
|
|
214
|
+
});
|
|
215
|
+
return walletClient;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Implementation of the interface method required by IAccountAbstractionWalletConnector
|
|
220
|
+
* @param eoaConnector - The EOA connector to use for signing transactions
|
|
221
|
+
* @param smartAccountAddress - The address of the smart account
|
|
222
|
+
*/
|
|
223
|
+
initialize(_a) {
|
|
224
|
+
return __awaiter(this, arguments, void 0, function* ({ eoaConnector, smartWalletAddress, }) {
|
|
225
|
+
this.initializedDeferredPromise = this.initializedDeferredPromise
|
|
226
|
+
? this.initializedDeferredPromise
|
|
227
|
+
: new DeferredPromise();
|
|
228
|
+
this.eoaConnector = eoaConnector;
|
|
229
|
+
this.eoaAddress = (yield eoaConnector.getAddress());
|
|
230
|
+
this.smartAccountAddress = smartWalletAddress;
|
|
231
|
+
this.smartAccount = (yield this.createEcdsaClient(eoaConnector));
|
|
232
|
+
yield this.checkIsDeployed();
|
|
233
|
+
this.initializedDeferredPromise.resolve();
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
createSessionClient(sessionKey, sessionConfig) {
|
|
237
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
238
|
+
if (!this.smartAccountAddress) {
|
|
239
|
+
throw new Error('Smart account address is not initialized');
|
|
240
|
+
}
|
|
241
|
+
if (!this.sessionKeyAddress) {
|
|
242
|
+
throw new Error('Session key address is not initialized');
|
|
243
|
+
}
|
|
244
|
+
return createZksyncSessionClient({
|
|
245
|
+
address: this.smartAccountAddress,
|
|
246
|
+
chain: getOrMapViemChain(this.evmNetworks[0]),
|
|
247
|
+
contracts: {
|
|
248
|
+
session: this.sessionKeyAddress,
|
|
249
|
+
},
|
|
250
|
+
sessionConfig,
|
|
251
|
+
sessionKey,
|
|
252
|
+
transport: http(),
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Creates a passkey client for ZKsync authentication
|
|
258
|
+
*
|
|
259
|
+
* This method initializes a passkey client using stored credentials and
|
|
260
|
+
* configures it with the necessary contract addresses and chain information.
|
|
261
|
+
*
|
|
262
|
+
*/
|
|
263
|
+
createPasskeyClient() {
|
|
264
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
265
|
+
if (!this.smartAccountAddress) {
|
|
266
|
+
throw new Error('Smart account address is not initialized');
|
|
267
|
+
}
|
|
268
|
+
if (!this.passkeyAddress) {
|
|
269
|
+
throw new Error('Passkey address is not initialized');
|
|
270
|
+
}
|
|
271
|
+
const storedCredentialPublicKey = StorageService.getItem('credentialPublicKey');
|
|
272
|
+
if (!storedCredentialPublicKey) {
|
|
273
|
+
throw new Error('Credential public key not found');
|
|
274
|
+
}
|
|
275
|
+
const credentialPublicKey = new Uint8Array(Object.values(storedCredentialPublicKey));
|
|
276
|
+
const publicClient = yield this.getTypedPublicClient();
|
|
277
|
+
const { chain } = publicClient;
|
|
278
|
+
if (!chain) {
|
|
279
|
+
throw new Error('Chain information not available');
|
|
280
|
+
}
|
|
281
|
+
const contractAddresses = {
|
|
282
|
+
accountFactory: this.factoryAddress,
|
|
283
|
+
passkey: this.passkeyAddress,
|
|
284
|
+
session: this.sessionKeyAddress,
|
|
285
|
+
};
|
|
286
|
+
this.passkeyClient = createZksyncPasskeyClient({
|
|
287
|
+
address: this.smartAccountAddress,
|
|
288
|
+
chain,
|
|
289
|
+
contracts: contractAddresses,
|
|
290
|
+
credentialPublicKey,
|
|
291
|
+
transport: http(),
|
|
292
|
+
userDisplayName: this.smartAccountAddress,
|
|
293
|
+
userName: this.smartAccountAddress,
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
registerPasskeyAndDeploy() {
|
|
298
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
299
|
+
if (!this.smartAccountAddress) {
|
|
300
|
+
throw new Error('Smart account address is not initialized');
|
|
301
|
+
}
|
|
302
|
+
const { credentialPublicKey, credentialId } = yield registerNewPasskey({
|
|
303
|
+
attestationType: 'none',
|
|
304
|
+
authenticatorSelection: {
|
|
305
|
+
authenticatorAttachment: 'platform',
|
|
306
|
+
requireResidentKey: false,
|
|
307
|
+
userVerification: 'required',
|
|
308
|
+
},
|
|
309
|
+
userDisplayName: this.smartAccountAddress,
|
|
310
|
+
userName: this.smartAccountAddress,
|
|
311
|
+
});
|
|
312
|
+
StorageService.setItem('credentialPublicKey', credentialPublicKey);
|
|
313
|
+
StorageService.setItem('credentialId', credentialId);
|
|
314
|
+
yield this.deploySmartAccount({
|
|
315
|
+
withPaymaster: true,
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
deploySmartAccount(_a) {
|
|
320
|
+
return __awaiter(this, arguments, void 0, function* ({ withPaymaster, }) {
|
|
321
|
+
if (!this.chainId) {
|
|
322
|
+
throw new Error('Chain ID is not initialized');
|
|
323
|
+
}
|
|
324
|
+
if (!this.eoaConnector) {
|
|
325
|
+
throw new Error('EOA connector is not initialized');
|
|
326
|
+
}
|
|
327
|
+
yield ensureEoaConnectorNetwork(this.eoaConnector, this.chainId);
|
|
328
|
+
if (withPaymaster && this.paymasterAddress) {
|
|
329
|
+
yield this.deploySmartAccountWithPaymaster();
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
yield this.deploySmartAccountWithoutPaymaster();
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
deploySmartAccountWithPaymaster() {
|
|
337
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
338
|
+
if (!this.paymasterAddress) {
|
|
339
|
+
throw new Error('Paymaster address is not initialized');
|
|
340
|
+
}
|
|
341
|
+
if (!this.smartAccountAddress) {
|
|
342
|
+
throw new Error('Smart account address is not initialized');
|
|
343
|
+
}
|
|
344
|
+
if (!this.eoaAddress) {
|
|
345
|
+
throw new Error('EOA address is not initialized');
|
|
346
|
+
}
|
|
347
|
+
const paymaster = this.paymasterAddress;
|
|
348
|
+
const publicClient = yield this.getTypedPublicClient();
|
|
349
|
+
const walletClient = yield this.getTypedWalletClient();
|
|
350
|
+
const deploymentParams = yield getDeploymentParameters({
|
|
351
|
+
enablePasskeys: this.enablePasskeys,
|
|
352
|
+
eoaAddress: this.eoaAddress,
|
|
353
|
+
passkeyAddress: this.passkeyAddress,
|
|
354
|
+
saltText: this.saltText,
|
|
355
|
+
sessionKeyAddress: this.sessionKeyAddress,
|
|
356
|
+
});
|
|
357
|
+
const { request } = yield simulateAccountDeployment(publicClient, walletClient, deploymentParams, this.factoryAddress, false);
|
|
358
|
+
const paymasterInput = getGeneralPaymasterInput({
|
|
359
|
+
innerInput: new Uint8Array(),
|
|
360
|
+
});
|
|
361
|
+
const requestWithPaymaster = Object.assign(Object.assign({}, request), { paymaster,
|
|
362
|
+
paymasterInput });
|
|
363
|
+
yield executeAccountDeployment(walletClient, publicClient, requestWithPaymaster, this.smartAccountAddress);
|
|
364
|
+
this._isSmartAccountDeployed = true;
|
|
365
|
+
});
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Deploys a new smart account contract
|
|
369
|
+
* @throws {ZkSyncConnectorError} If deployment fails
|
|
370
|
+
* @testable This method can be mocked in tests
|
|
371
|
+
*/
|
|
372
|
+
deploySmartAccountWithoutPaymaster() {
|
|
373
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
374
|
+
if (!this.eoaConnector) {
|
|
375
|
+
throw new Error('EOA connector is not initialized');
|
|
376
|
+
}
|
|
377
|
+
if (!this.smartAccountAddress) {
|
|
378
|
+
throw new Error('Smart account address is not initialized');
|
|
379
|
+
}
|
|
380
|
+
const walletClient = yield this.getTypedWalletClient();
|
|
381
|
+
const publicClient = yield this.getTypedPublicClient();
|
|
382
|
+
const deploymentParams = yield this.getDeploymentParameters();
|
|
383
|
+
// Simulate the contract deployment first
|
|
384
|
+
const { request } = yield simulateAccountDeployment(publicClient, walletClient, deploymentParams, this.factoryAddress, false);
|
|
385
|
+
// Execute the deployment transaction
|
|
386
|
+
yield executeAccountDeployment(walletClient, publicClient, request, this.smartAccountAddress);
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
/**
|
|
390
|
+
* Gets typed public client from EOA connector
|
|
391
|
+
* @throws {ZkSyncConnectorError} If public client cannot be obtained
|
|
392
|
+
* @testable This method can be mocked in tests
|
|
393
|
+
*/
|
|
394
|
+
getTypedPublicClient() {
|
|
395
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
396
|
+
if (!this.eoaConnector) {
|
|
397
|
+
throw new Error('EOA connector is not initialized');
|
|
398
|
+
}
|
|
399
|
+
const publicClient = yield this.eoaConnector.getPublicClient();
|
|
400
|
+
if (!publicClient) {
|
|
401
|
+
throw new Error('Failed to get public client from EOA connector');
|
|
402
|
+
}
|
|
403
|
+
return publicClient;
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Gets typed wallet client from EOA connector on the correct chain
|
|
408
|
+
* @throws {ZkSyncConnectorError} If wallet client cannot be obtained
|
|
409
|
+
* @testable This method can be mocked in tests
|
|
410
|
+
*/
|
|
411
|
+
getTypedWalletClient() {
|
|
412
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
413
|
+
if (!this.eoaConnector) {
|
|
414
|
+
throw new Error('EOA connector is not initialized');
|
|
415
|
+
}
|
|
416
|
+
const walletClient = yield this.eoaConnector.getWalletClient();
|
|
417
|
+
if (!walletClient) {
|
|
418
|
+
throw new Error('Failed to get wallet client from EOA connector');
|
|
419
|
+
}
|
|
420
|
+
return walletClient
|
|
421
|
+
.extend(publicActions)
|
|
422
|
+
.extend(walletActions)
|
|
423
|
+
.extend(eip712WalletActions())
|
|
424
|
+
.extend(zksyncSsoEcdsaWalletActions);
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* Returns the parameters needed for deploying the smart account
|
|
429
|
+
* @returns Deployment parameters object
|
|
430
|
+
* @testable This method can be overridden in tests
|
|
431
|
+
*/
|
|
432
|
+
getDeploymentParameters() {
|
|
433
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
434
|
+
if (!this.eoaAddress) {
|
|
435
|
+
throw new Error('EOA address is not initialized');
|
|
436
|
+
}
|
|
437
|
+
const initialValidators = [];
|
|
438
|
+
const initialK1Owners = [this.eoaAddress];
|
|
439
|
+
// TODO: revisit this logic, maybe we should always add the passkey module data,
|
|
440
|
+
// otherwise if people active passkeys later, old accounts will not be able to use passkey module
|
|
441
|
+
if (this.enablePasskeys && this.passkeyAddress) {
|
|
442
|
+
const encodedPasskeyModuleData = yield getEncodedPasskeyModuleData({
|
|
443
|
+
passkeyAddress: this.passkeyAddress,
|
|
444
|
+
});
|
|
445
|
+
initialValidators.push(encodedPasskeyModuleData);
|
|
446
|
+
}
|
|
447
|
+
if (this.sessionKeyAddress) {
|
|
448
|
+
const encodedSessionKeyModuleData = encodeModuleData({
|
|
449
|
+
address: this.sessionKeyAddress,
|
|
450
|
+
parameters: '0x',
|
|
451
|
+
});
|
|
452
|
+
initialValidators.push(encodedSessionKeyModuleData);
|
|
453
|
+
}
|
|
454
|
+
return {
|
|
455
|
+
initialK1Owners,
|
|
456
|
+
initialValidators,
|
|
457
|
+
salt: getSalt(this.saltText),
|
|
458
|
+
};
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
signMessage(message) {
|
|
462
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
463
|
+
const walletClient = this.getWalletClient();
|
|
464
|
+
if (!walletClient) {
|
|
465
|
+
throw new Error('Error fetching signer');
|
|
466
|
+
}
|
|
467
|
+
return walletClient.signMessage({
|
|
468
|
+
account: walletClient.account,
|
|
469
|
+
message,
|
|
470
|
+
});
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
/**
|
|
474
|
+
* Checks if a smart account is deployed
|
|
475
|
+
* @throws {ZkSyncConnectorError} If the check fails
|
|
476
|
+
* @returns Promise that resolves when the check is complete
|
|
477
|
+
*/
|
|
478
|
+
checkIsDeployed() {
|
|
479
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
480
|
+
if (!this.smartAccountAddress) {
|
|
481
|
+
throw new Error('Smart account address is not initialized');
|
|
482
|
+
}
|
|
483
|
+
const client = yield this.getPublicClient();
|
|
484
|
+
if (!client) {
|
|
485
|
+
throw new Error('Failed to get public client from EOA connector');
|
|
486
|
+
}
|
|
487
|
+
const code = yield client.getCode({
|
|
488
|
+
address: this.smartAccountAddress,
|
|
489
|
+
});
|
|
490
|
+
const isDeployed = Boolean(code);
|
|
491
|
+
this._isSmartAccountDeployed = isDeployed;
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
getAddress() {
|
|
495
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
496
|
+
var _a;
|
|
497
|
+
yield ((_a = this.initializedDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
|
|
498
|
+
if (!this.smartAccount) {
|
|
499
|
+
throw new Error('Smart account is not initialized');
|
|
500
|
+
}
|
|
501
|
+
return this.smartAccountAddress;
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
validateActiveWallet(expectedAddress) {
|
|
505
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
506
|
+
const currentAddress = yield this.getAddress();
|
|
507
|
+
if (currentAddress !== expectedAddress) {
|
|
508
|
+
throw new DynamicError('Invalid active wallet');
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
}
|
|
512
|
+
isSmartAccountDeployed() {
|
|
513
|
+
return __awaiter(this, arguments, void 0, function* (refetch = false) {
|
|
514
|
+
if (refetch) {
|
|
515
|
+
yield this.checkIsDeployed();
|
|
516
|
+
}
|
|
517
|
+
return this._isSmartAccountDeployed;
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
export { ZKsyncConnector };
|
package/src/ZeroDevConnector.cjs
CHANGED
|
@@ -16,8 +16,10 @@ var createEcsdaKernelAccountClient = require('./utils/createEcsdaKernelAccountCl
|
|
|
16
16
|
var getEcdsaValidator = require('./utils/getEcdsaValidator.cjs');
|
|
17
17
|
var getEntryPoint = require('./utils/getEntryPoint.cjs');
|
|
18
18
|
var getKernelVersion = require('./utils/getKernelVersion.cjs');
|
|
19
|
+
require('zksync-sso/utils');
|
|
20
|
+
var AccountAbstractionConnector = require('./AccountAbstractionConnector.cjs');
|
|
19
21
|
|
|
20
|
-
class ZeroDevConnector extends
|
|
22
|
+
class ZeroDevConnector extends AccountAbstractionConnector.AccountAbstractionConnector {
|
|
21
23
|
constructor(opts) {
|
|
22
24
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
23
25
|
super(opts);
|
|
@@ -28,7 +30,6 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
28
30
|
this.ChainWallet = ethereumCore.EthereumWallet;
|
|
29
31
|
this.connectedChain = 'EVM';
|
|
30
32
|
this.supportedChains = ['ETH', 'EVM'];
|
|
31
|
-
this.isGasSponsorshipDisabled = false;
|
|
32
33
|
this.isEmbeddedWallet = true;
|
|
33
34
|
this.providersFromApi = [];
|
|
34
35
|
this.name = 'ZeroDev';
|
|
@@ -60,6 +61,9 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
60
61
|
this.defaultChainId = defaultProvider === null || defaultProvider === void 0 ? void 0 : defaultProvider.chain;
|
|
61
62
|
this.ecdsaProviderType = (_j = opts.apiProviders.zerodev) === null || _j === void 0 ? void 0 : _j.ecdsaProviderType;
|
|
62
63
|
}
|
|
64
|
+
confirmTransactionStatus() {
|
|
65
|
+
throw new Error('confirmTransactionStatus not implemented in ZeroDevConnector');
|
|
66
|
+
}
|
|
63
67
|
get currentNetworkProvider() {
|
|
64
68
|
// check if the last used chain id is in the provider map
|
|
65
69
|
if (this.providerMap[this.lastUsedChainId]) {
|
|
@@ -104,13 +108,6 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
104
108
|
handleChainChange(chainId);
|
|
105
109
|
});
|
|
106
110
|
}
|
|
107
|
-
/**
|
|
108
|
-
* @deprecated You should get the EOA connector by passing the SCW to getEOAConnector,
|
|
109
|
-
* from the useSmartWallet hook
|
|
110
|
-
*/
|
|
111
|
-
getEOAConnector() {
|
|
112
|
-
return this.eoaConnector;
|
|
113
|
-
}
|
|
114
111
|
getAccountAbstractionProvider({ withSponsorship, } = {}) {
|
|
115
112
|
if (withSponsorship && this.kernelClientWithSponsorship) {
|
|
116
113
|
return this.kernelClientWithSponsorship;
|
|
@@ -122,6 +119,14 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
122
119
|
utils.StorageService.removeItem(constants.ZERO_DEV_LAST_USED_CHAIN_ID_KEY);
|
|
123
120
|
});
|
|
124
121
|
}
|
|
122
|
+
initialize(_a) {
|
|
123
|
+
return _tslib.__awaiter(this, arguments, void 0, function* ({ smartWalletAddress, eoaAddress, eoaConnector, properties, shouldSetEoaConnector, }) {
|
|
124
|
+
yield this.registerEoa(Object.assign({ eoaAddress,
|
|
125
|
+
eoaConnector,
|
|
126
|
+
shouldSetEoaConnector,
|
|
127
|
+
smartWalletAddress }, properties));
|
|
128
|
+
});
|
|
129
|
+
}
|
|
125
130
|
registerEoa(_a) {
|
|
126
131
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
127
132
|
var { smartWalletAddress, eoaAddress, eoaConnector, shouldSetEoaConnector = false } = _a, properties = _tslib.__rest(_a, ["smartWalletAddress", "eoaAddress", "eoaConnector", "shouldSetEoaConnector"]);
|
|
@@ -369,7 +374,7 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
369
374
|
onSendTransaction: (_b) => _tslib.__awaiter(this, [_b], void 0, function* ({ transaction }) {
|
|
370
375
|
try {
|
|
371
376
|
this._walletUiUtils.disabledConfirmationOnce();
|
|
372
|
-
const effectiveProvider = this.isGasSponsorshipDisabled
|
|
377
|
+
const effectiveProvider = this.isGasSponsorshipDisabled()
|
|
373
378
|
? provider
|
|
374
379
|
: this.kernelClientWithSponsorship;
|
|
375
380
|
if (!effectiveProvider) {
|
|
@@ -428,11 +433,6 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
428
433
|
return provider;
|
|
429
434
|
});
|
|
430
435
|
}
|
|
431
|
-
getSigner() {
|
|
432
|
-
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
433
|
-
return this.getWalletClient();
|
|
434
|
-
});
|
|
435
|
-
}
|
|
436
436
|
formatUserOperation(params) {
|
|
437
437
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
438
438
|
var _a;
|
|
@@ -540,9 +540,6 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
540
540
|
return sponsored;
|
|
541
541
|
});
|
|
542
542
|
}
|
|
543
|
-
disableGasSponsorshipOnce() {
|
|
544
|
-
this.isGasSponsorshipDisabled = true;
|
|
545
|
-
}
|
|
546
543
|
getBalance(address) {
|
|
547
544
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
548
545
|
var _a;
|
|
@@ -561,17 +558,6 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
561
558
|
return client.signMessage({ message: messageToSign });
|
|
562
559
|
});
|
|
563
560
|
}
|
|
564
|
-
createUiTransaction(from) {
|
|
565
|
-
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
566
|
-
yield this.validateActiveWallet(from);
|
|
567
|
-
const walletClient = this.getWalletClient();
|
|
568
|
-
const publicClient = yield this.getPublicClient();
|
|
569
|
-
if (!publicClient || !walletClient) {
|
|
570
|
-
throw new utils.DynamicError('No public client available');
|
|
571
|
-
}
|
|
572
|
-
return ethereumCore.createViemUiTransaction({ from, publicClient, walletClient });
|
|
573
|
-
});
|
|
574
|
-
}
|
|
575
561
|
validateActiveWallet(expectedAddress) {
|
|
576
562
|
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
577
563
|
if (this.enableEIP7702Mode) {
|
|
@@ -595,15 +581,6 @@ class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
|
595
581
|
});
|
|
596
582
|
});
|
|
597
583
|
}
|
|
598
|
-
getBlockExplorerUrlsForCurrentNetwork() {
|
|
599
|
-
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
600
|
-
var _a, _b;
|
|
601
|
-
return (_b = (_a = this.eoaConnector) === null || _a === void 0 ? void 0 : _a.getBlockExplorerUrlsForCurrentNetwork()) !== null && _b !== void 0 ? _b : [];
|
|
602
|
-
});
|
|
603
|
-
}
|
|
604
|
-
getEnabledNetworks() {
|
|
605
|
-
return this.evmNetworks;
|
|
606
|
-
}
|
|
607
584
|
}
|
|
608
585
|
|
|
609
586
|
exports.ZeroDevConnector = ZeroDevConnector;
|