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

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