@dynamic-labs/ethereum-aa 2.0.0-alpha.3 → 2.0.0-alpha.30

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.
@@ -1,15 +1,14 @@
1
1
  import { __awaiter } from '../_virtual/_tslib.js';
2
- import { ECDSAProvider, convertWalletClientToAccountSigner } from '@zerodev/sdk';
3
- import { custom, createWalletClient, isHex, fromHex, formatEther } from 'viem';
2
+ import { createEcdsaKernelAccountClient } from '@zerodev/presets';
3
+ import { publicActions, custom, createWalletClient, isHex, fromHex, formatEther } from 'viem';
4
+ import { walletClientToSmartAccountSigner } from 'permissionless';
4
5
  import { WalletConnectorBase } from '@dynamic-labs/wallet-connector-core';
5
- import { confirmationTransport, unFormatTransaction } from '@dynamic-labs/viem-utils';
6
+ import { confirmationTransport, chainsMap, unFormatTransaction, createViemUiTransaction } from '@dynamic-labs/viem-utils';
6
7
  import { parseEvmNetworks, DynamicError, DeferredPromise, wrapMethodWithCallback, TransactionGasCannotBeSponsoredError, InsufficientFundsError } from '@dynamic-labs/utils';
8
+ import { cachedChainIdKey, fetchChain } from './utils/fetchChain.js';
7
9
  import { logger } from './utils/logger.js';
8
10
 
9
11
  class ZeroDevConnector extends WalletConnectorBase {
10
- get key() {
11
- return 'zerodev';
12
- }
13
12
  constructor(opts) {
14
13
  var _a;
15
14
  super(opts);
@@ -18,6 +17,14 @@ class ZeroDevConnector extends WalletConnectorBase {
18
17
  this.isGasSponsorshipDisabled = false;
19
18
  this.isEmbeddedWallet = true;
20
19
  this.name = 'ZeroDev';
20
+ this.overrideKey = 'zerodev';
21
+ this.walletFallback = {
22
+ brand: {
23
+ alt: 'Smart Wallet',
24
+ spriteId: 'smartwallet',
25
+ },
26
+ name: 'ZeroDev',
27
+ };
21
28
  const zeroDevProjectId = (_a = opts.apiProviders.zerodev) === null || _a === void 0 ? void 0 : _a.clientId;
22
29
  if (!zeroDevProjectId) {
23
30
  throw new Error('Missing ZeroDev project ID provided. Add your ZeroDev project id to your project configuration via the Dynamic Labs dashboard.');
@@ -30,28 +37,35 @@ class ZeroDevConnector extends WalletConnectorBase {
30
37
  return this.eoaConnector;
31
38
  }
32
39
  getAccountAbstractionProvider() {
33
- return this.zeroDevProvider;
40
+ return this.kernelClient;
41
+ }
42
+ endSession() {
43
+ return __awaiter(this, void 0, void 0, function* () {
44
+ localStorage.removeItem(cachedChainIdKey);
45
+ });
34
46
  }
35
47
  setEoaConnector(connector) {
36
48
  return __awaiter(this, void 0, void 0, function* () {
37
- this.zeroDevProviderDeferredPromise = new DeferredPromise();
49
+ this.kernelClientDeferredPromise = new DeferredPromise();
38
50
  this.eoaConnector = connector;
39
51
  const signer = yield this.eoaConnector.getSigner();
40
- if (!signer) {
52
+ if (!(signer === null || signer === void 0 ? void 0 : signer.account)) {
41
53
  return;
42
54
  }
43
- const zeroDevProvider = yield ECDSAProvider.init({
44
- bundlerProvider: 'STACKUP',
45
- owner: convertWalletClientToAccountSigner(signer),
55
+ const kernelClient = yield createEcdsaKernelAccountClient({
56
+ chain: yield fetchChain(this.projectId),
57
+ paymaster: 'NONE',
46
58
  projectId: this.projectId,
59
+ provider: ZeroDevConnector.bundlerProvider,
60
+ signer: walletClientToSmartAccountSigner(signer),
47
61
  });
48
- wrapMethodWithCallback(zeroDevProvider, 'sendUserOperation', (original, ...args) => {
62
+ wrapMethodWithCallback(kernelClient, 'sendUserOperation', (original, ...args) => {
49
63
  this._walletUiUtils.disabledConfirmationOnce();
50
64
  return original(...args);
51
65
  });
52
- this.zeroDevProvider = zeroDevProvider;
66
+ this.kernelClient = kernelClient;
53
67
  yield this.checkIsProjectChainEnabled();
54
- this.zeroDevProviderDeferredPromise.resolve();
68
+ this.kernelClientDeferredPromise.resolve();
55
69
  });
56
70
  }
57
71
  checkIsProjectChainEnabled() {
@@ -66,69 +80,67 @@ class ZeroDevConnector extends WalletConnectorBase {
66
80
  }
67
81
  });
68
82
  }
69
- getProviderWithSponsorshipValidation() {
83
+ getKernelClientWithSponsorshipValidation() {
70
84
  return __awaiter(this, void 0, void 0, function* () {
71
- if (this.providerWithSponsorship) {
72
- return this.providerWithSponsorship;
85
+ if (this.kernelClientWithSponsorship) {
86
+ return this.kernelClientWithSponsorship;
73
87
  }
74
88
  const { eoaConnector } = this;
75
89
  if (!eoaConnector)
76
90
  throw new DynamicError('No EOA connector');
77
91
  const signer = yield eoaConnector.getSigner();
78
- this.providerWithSponsorship = yield ECDSAProvider.init({
79
- bundlerProvider: 'STACKUP',
80
- opts: {
81
- paymasterConfig: {
82
- onlySendSponsoredTransaction: true,
83
- policy: 'VERIFYING_PAYMASTER',
84
- },
85
- },
86
- owner: convertWalletClientToAccountSigner(signer),
92
+ this.kernelClientWithSponsorship = yield createEcdsaKernelAccountClient({
93
+ chain: yield fetchChain(this.projectId),
94
+ paymaster: 'SPONSOR',
87
95
  projectId: this.projectId,
96
+ provider: ZeroDevConnector.bundlerProvider,
97
+ signer: walletClientToSmartAccountSigner(signer),
88
98
  });
89
- wrapMethodWithCallback(this.providerWithSponsorship, 'sendUserOperation', (original, ...args) => {
99
+ wrapMethodWithCallback(this.kernelClientWithSponsorship, 'sendUserOperation', (original, ...args) => {
90
100
  this._walletUiUtils.disabledConfirmationOnce();
91
101
  return original(...args);
92
102
  });
93
- return this.providerWithSponsorship;
103
+ return this.kernelClientWithSponsorship;
94
104
  });
95
105
  }
96
- fetchPublicAddress() {
97
- var _a, _b;
106
+ getAddress() {
107
+ var _a, _b, _c;
98
108
  return __awaiter(this, void 0, void 0, function* () {
99
- yield ((_a = this.zeroDevProviderDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
100
- return (_b = this.zeroDevProvider) === null || _b === void 0 ? void 0 : _b.getAddress();
109
+ yield ((_a = this.kernelClientDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
110
+ return (_c = (_b = this.kernelClient) === null || _b === void 0 ? void 0 : _b.account) === null || _c === void 0 ? void 0 : _c.address;
101
111
  });
102
112
  }
103
113
  getConnectedAccounts() {
104
- var _a;
114
+ var _a, _b, _c;
105
115
  return __awaiter(this, void 0, void 0, function* () {
106
- yield ((_a = this.zeroDevProviderDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
107
- return this.zeroDevProvider
108
- ? [yield this.zeroDevProvider.getAddress()]
116
+ yield ((_a = this.kernelClientDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
117
+ return ((_c = (_b = this.kernelClient) === null || _b === void 0 ? void 0 : _b.account) === null || _c === void 0 ? void 0 : _c.address)
118
+ ? [yield this.kernelClient.account.address]
109
119
  : [];
110
120
  });
111
121
  }
112
122
  getNetwork() {
113
- var _a, _b;
123
+ var _a, _b, _c;
114
124
  return __awaiter(this, void 0, void 0, function* () {
115
- yield ((_a = this.zeroDevProviderDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
116
- return (_b = this.zeroDevProvider) === null || _b === void 0 ? void 0 : _b.rpcClient.chain.id;
125
+ yield ((_a = this.kernelClientDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
126
+ return (_c = (_b = this.kernelClient) === null || _b === void 0 ? void 0 : _b.chain) === null || _c === void 0 ? void 0 : _c.id;
117
127
  });
118
128
  }
119
129
  getTransport(provider) {
120
130
  const transport = confirmationTransport({
121
- connector: this,
122
131
  onPersonalSign: ({ message }) => __awaiter(this, void 0, void 0, function* () {
123
132
  this._walletUiUtils.disabledConfirmationOnce();
124
- return provider.signMessage(message);
133
+ return provider.signMessage({
134
+ account: provider.account,
135
+ message,
136
+ });
125
137
  }),
126
138
  onSendTransaction: ({ transaction }) => __awaiter(this, void 0, void 0, function* () {
127
139
  try {
128
140
  this._walletUiUtils.disabledConfirmationOnce();
129
141
  const effectiveProvider = this.isGasSponsorshipDisabled
130
142
  ? provider
131
- : yield this.getProviderWithSponsorshipValidation();
143
+ : yield this.getKernelClientWithSponsorshipValidation();
132
144
  const response = yield effectiveProvider.sendTransaction(unFormatTransaction(transaction));
133
145
  return response;
134
146
  }
@@ -146,58 +158,69 @@ class ZeroDevConnector extends WalletConnectorBase {
146
158
  onSignTypedData: ({ message }) => __awaiter(this, void 0, void 0, function* () {
147
159
  this._walletUiUtils.disabledConfirmationOnce();
148
160
  const signTypedData = JSON.parse(message);
149
- return provider.signTypedData(signTypedData);
161
+ return provider.signTypedData({
162
+ account: provider.account,
163
+ domain: signTypedData.domain,
164
+ message: signTypedData.message,
165
+ primaryType: signTypedData.primaryType,
166
+ types: signTypedData.types,
167
+ });
150
168
  }),
151
- provider: provider.rpcClient,
169
+ provider: provider.extend(publicActions),
152
170
  transport: custom(provider),
171
+ walletConnector: this,
153
172
  walletUiUtils: this._walletUiUtils,
154
173
  });
155
174
  return transport;
156
175
  }
157
- getWalletClient() {
158
- const provider = this.zeroDevProvider;
176
+ getWalletClient(chainId) {
177
+ var _a;
178
+ const provider = this.kernelClient;
159
179
  if (!provider)
160
180
  throw new DynamicError('No provider');
161
181
  const transport = this.getTransport(provider);
182
+ const address = (_a = provider.account) === null || _a === void 0 ? void 0 : _a.address;
162
183
  const walletClient = createWalletClient({
184
+ account: address,
185
+ chain: chainId ? chainsMap[chainId] : provider.chain,
163
186
  transport,
164
187
  });
165
188
  return walletClient;
166
189
  }
167
190
  getPublicClient() {
168
191
  return __awaiter(this, void 0, void 0, function* () {
169
- const provider = this.zeroDevProvider;
192
+ const provider = this.kernelClient.extend(publicActions);
170
193
  if (!provider)
171
194
  throw new DynamicError('No provider');
172
- return provider.rpcClient;
195
+ return provider;
173
196
  });
174
197
  }
175
198
  getSigner() {
176
199
  return __awaiter(this, void 0, void 0, function* () {
177
- const provider = this.zeroDevProvider;
178
- if (!provider)
179
- throw new DynamicError('No provider');
180
- const transport = this.getTransport(provider);
181
- const address = yield provider.getAddress();
182
- const walletClient = createWalletClient({
183
- account: address,
184
- transport,
185
- });
186
- return walletClient;
200
+ return this.getWalletClient();
187
201
  });
188
202
  }
189
203
  canSponsorTransactionGas(transaction) {
190
- var _a;
191
204
  return __awaiter(this, void 0, void 0, function* () {
192
205
  try {
206
+ yield this.getKernelClientWithSponsorshipValidation();
193
207
  const userOperation = {
194
- data: transaction.data ? transaction.data : '0x',
195
- target: transaction.to,
196
- value: isHex(transaction.value)
197
- ? fromHex(transaction.value, 'bigint')
198
- : transaction.value,
208
+ callData: yield this.kernelClientWithSponsorship.account.encodeCallData({
209
+ data: transaction.data ? transaction.data : '0x',
210
+ to: transaction.to,
211
+ /**
212
+ * if value is undefined, it will be set to 0x0 so the sponsorship
213
+ * check does not fail
214
+ */
215
+ value: transaction.value && isHex(transaction.value)
216
+ ? fromHex(transaction.value, 'bigint')
217
+ : '0x0',
218
+ }),
199
219
  };
200
- const result = yield ((_a = this.zeroDevProvider) === null || _a === void 0 ? void 0 : _a.buildUserOperation(userOperation));
220
+ const result = yield this.kernelClientWithSponsorship.prepareUserOperationRequest({
221
+ account: this.kernelClientWithSponsorship.account,
222
+ userOperation,
223
+ });
201
224
  if (!result)
202
225
  return false;
203
226
  return result.paymasterAndData !== '0x';
@@ -212,12 +235,11 @@ class ZeroDevConnector extends WalletConnectorBase {
212
235
  this.isGasSponsorshipDisabled = true;
213
236
  }
214
237
  getBalance() {
215
- var _a;
216
238
  return __awaiter(this, void 0, void 0, function* () {
217
- const rpcClient = yield ((_a = this.zeroDevProvider) === null || _a === void 0 ? void 0 : _a.rpcClient);
239
+ const rpcClient = this.kernelClient.extend(publicActions);
218
240
  if (!rpcClient)
219
241
  throw new DynamicError('No RPC client');
220
- const address = yield this.fetchPublicAddress();
242
+ const address = yield this.getAddress();
221
243
  if (!address)
222
244
  return;
223
245
  return formatEther(yield rpcClient.getBalance({ address: address }));
@@ -226,7 +248,7 @@ class ZeroDevConnector extends WalletConnectorBase {
226
248
  signMessage(messageToSign) {
227
249
  return __awaiter(this, void 0, void 0, function* () {
228
250
  const client = yield this.getSigner();
229
- const account = yield this.fetchPublicAddress();
251
+ const account = yield this.getAddress();
230
252
  if (!account || !client)
231
253
  return;
232
254
  return client.signMessage({
@@ -235,6 +257,16 @@ class ZeroDevConnector extends WalletConnectorBase {
235
257
  });
236
258
  });
237
259
  }
260
+ createUiTransaction(from) {
261
+ return __awaiter(this, void 0, void 0, function* () {
262
+ const walletClient = this.getWalletClient();
263
+ const publicClient = yield this.getPublicClient();
264
+ if (!publicClient || !walletClient) {
265
+ throw new DynamicError('No public client available');
266
+ }
267
+ return createViemUiTransaction({ from, publicClient, walletClient });
268
+ });
269
+ }
238
270
  }
239
271
 
240
272
  export { ZeroDevConnector };
package/src/index.cjs CHANGED
@@ -6,6 +6,12 @@ var ZeroDevConnector = require('./ZeroDevConnector.cjs');
6
6
  var ethereumAa = require('./ethereum-aa.cjs');
7
7
  var isZeroDevConnector = require('./utils/isZeroDevConnector.cjs');
8
8
 
9
+ const ZeroDevSmartWalletConnectorsWithConfig = ({ bundlerProvider, } = {}) => {
10
+ if (bundlerProvider) {
11
+ ZeroDevConnector.ZeroDevConnector.bundlerProvider = bundlerProvider;
12
+ }
13
+ return ZeroDevSmartWalletConnectors;
14
+ };
9
15
  const ZeroDevSmartWalletConnectors = (props) => {
10
16
  var _a;
11
17
  if ((_a = props.apiProviders) === null || _a === void 0 ? void 0 : _a.zerodev) {
@@ -17,3 +23,4 @@ const ZeroDevSmartWalletConnectors = (props) => {
17
23
  exports.EthereumAaConnector = ethereumAa.EthereumAaConnector;
18
24
  exports.isZeroDevConnector = isZeroDevConnector.isZeroDevConnector;
19
25
  exports.ZeroDevSmartWalletConnectors = ZeroDevSmartWalletConnectors;
26
+ exports.ZeroDevSmartWalletConnectorsWithConfig = ZeroDevSmartWalletConnectorsWithConfig;
package/src/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
+ import { Provider as BundlerProvider } from '@zerodev/presets';
1
2
  import { WalletConnectorConstructor } from '@dynamic-labs/wallet-connector-core';
2
3
  export * from './ethereum-aa';
3
4
  export { isZeroDevConnector } from './utils/isZeroDevConnector';
5
+ export declare const ZeroDevSmartWalletConnectorsWithConfig: ({ bundlerProvider, }?: {
6
+ bundlerProvider?: BundlerProvider | undefined;
7
+ }) => (props: any) => WalletConnectorConstructor[];
4
8
  export declare const ZeroDevSmartWalletConnectors: (props: any) => WalletConnectorConstructor[];
package/src/index.js CHANGED
@@ -2,6 +2,12 @@ import { ZeroDevConnector } from './ZeroDevConnector.js';
2
2
  export { EthereumAaConnector } from './ethereum-aa.js';
3
3
  export { isZeroDevConnector } from './utils/isZeroDevConnector.js';
4
4
 
5
+ const ZeroDevSmartWalletConnectorsWithConfig = ({ bundlerProvider, } = {}) => {
6
+ if (bundlerProvider) {
7
+ ZeroDevConnector.bundlerProvider = bundlerProvider;
8
+ }
9
+ return ZeroDevSmartWalletConnectors;
10
+ };
5
11
  const ZeroDevSmartWalletConnectors = (props) => {
6
12
  var _a;
7
13
  if ((_a = props.apiProviders) === null || _a === void 0 ? void 0 : _a.zerodev) {
@@ -10,4 +16,4 @@ const ZeroDevSmartWalletConnectors = (props) => {
10
16
  return [];
11
17
  };
12
18
 
13
- export { ZeroDevSmartWalletConnectors };
19
+ export { ZeroDevSmartWalletConnectors, ZeroDevSmartWalletConnectorsWithConfig };
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
5
+ var _tslib = require('../../_virtual/_tslib.cjs');
6
+ var viemUtils = require('@dynamic-labs/viem-utils');
7
+ var logger = require('./logger.cjs');
8
+
9
+ const cachedChainIdKey = 'dynamic_zd_chain_id';
10
+ const fetchChain = (projectId) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
11
+ try {
12
+ const cachedChainId = localStorage.getItem(cachedChainIdKey);
13
+ if (cachedChainId) {
14
+ return viemUtils.chainsMap[cachedChainId];
15
+ }
16
+ const response = yield (yield fetch(`https://prod-api.zerodev.app/projects/${projectId}`)).json();
17
+ localStorage.setItem(cachedChainIdKey, response.chainId);
18
+ return viemUtils.chainsMap[response.chainId];
19
+ }
20
+ catch (err) {
21
+ logger.logger.error('Failed to fetch ZeroDev project settings from ZeroDev API ' +
22
+ 'This is needed to fetch the chain id so that we know which chain the smart contract is on');
23
+ throw err;
24
+ }
25
+ });
26
+
27
+ exports.cachedChainIdKey = cachedChainIdKey;
28
+ exports.fetchChain = fetchChain;
@@ -0,0 +1,3 @@
1
+ import { type Chain } from 'viem/chains';
2
+ export declare const cachedChainIdKey = "dynamic_zd_chain_id";
3
+ export declare const fetchChain: (projectId: string) => Promise<Chain>;
@@ -0,0 +1,23 @@
1
+ import { __awaiter } from '../../_virtual/_tslib.js';
2
+ import { chainsMap } from '@dynamic-labs/viem-utils';
3
+ import { logger } from './logger.js';
4
+
5
+ const cachedChainIdKey = 'dynamic_zd_chain_id';
6
+ const fetchChain = (projectId) => __awaiter(void 0, void 0, void 0, function* () {
7
+ try {
8
+ const cachedChainId = localStorage.getItem(cachedChainIdKey);
9
+ if (cachedChainId) {
10
+ return chainsMap[cachedChainId];
11
+ }
12
+ const response = yield (yield fetch(`https://prod-api.zerodev.app/projects/${projectId}`)).json();
13
+ localStorage.setItem(cachedChainIdKey, response.chainId);
14
+ return chainsMap[response.chainId];
15
+ }
16
+ catch (err) {
17
+ logger.error('Failed to fetch ZeroDev project settings from ZeroDev API ' +
18
+ 'This is needed to fetch the chain id so that we know which chain the smart contract is on');
19
+ throw err;
20
+ }
21
+ });
22
+
23
+ export { cachedChainIdKey, fetchChain };
@@ -0,0 +1,3 @@
1
+ export * from './fetchChain';
2
+ export * from './logger';
3
+ export * from './isZeroDevConnector';