@dynamic-labs/ethereum-aa 2.0.0-alpha.7 → 2.0.0-alpha.9
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 +17 -0
- package/_virtual/_tslib.cjs +35 -0
- package/_virtual/_tslib.js +31 -0
- package/package.json +10 -9
- package/src/ZeroDevConnector.cjs +259 -0
- package/src/ZeroDevConnector.d.ts +5 -4
- package/src/ZeroDevConnector.js +255 -0
- package/src/index.cjs +2 -3
- package/src/index.js +2 -3
- package/src/utils/fetchChain.cjs +49 -0
- package/src/utils/fetchChain.d.ts +3 -0
- package/src/utils/fetchChain.js +24 -0
- package/src/utils/index.d.ts +3 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,21 @@
|
|
|
1
1
|
|
|
2
|
+
## [2.0.0-alpha.9](https://github.com/dynamic-labs/DynamicAuth/compare/v2.0.0-alpha.8...v2.0.0-alpha.9) (2024-03-06)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* solana connector new sendTransaction method ([#4842](https://github.com/dynamic-labs/DynamicAuth/issues/4842)) ([0b198e3](https://github.com/dynamic-labs/DynamicAuth/commit/0b198e30d83fbbc8d506654d87cbfad403fda289))
|
|
8
|
+
* specify solana network when using phantom redirect deeplinking ([#4863](https://github.com/dynamic-labs/DynamicAuth/issues/4863)) ([fb4ee7c](https://github.com/dynamic-labs/DynamicAuth/commit/fb4ee7cfc0493c9c85b6ccb31954842556c58aa4))
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* isLoggedIn should return true even when there is no primary wallet ([#4875](https://github.com/dynamic-labs/DynamicAuth/issues/4875)) ([f396e22](https://github.com/dynamic-labs/DynamicAuth/commit/f396e22b9d809b05ac52194ffa4346f3591d17fe))
|
|
14
|
+
* update btckit network conversion for signPsbt ([a6009e1](https://github.com/dynamic-labs/DynamicAuth/commit/a6009e18c453b4e65545455fea0e52ed7a983b4d))
|
|
15
|
+
* user getting logged out when signing in with email linked to a unavailable wallet ([#4858](https://github.com/dynamic-labs/DynamicAuth/issues/4858)) ([8653e13](https://github.com/dynamic-labs/DynamicAuth/commit/8653e13d2067dd0161e660b4374c08a9fe0bc203))
|
|
16
|
+
|
|
17
|
+
## [2.0.0-alpha.8](https://github.com/dynamic-labs/DynamicAuth/compare/v2.0.0-alpha.7...v2.0.0-alpha.8) (2024-03-04)
|
|
18
|
+
|
|
2
19
|
## [2.0.0-alpha.7](https://github.com/dynamic-labs/DynamicAuth/compare/v2.0.0-alpha.6...v2.0.0-alpha.7) (2024-02-28)
|
|
3
20
|
|
|
4
21
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
/******************************************************************************
|
|
6
|
+
Copyright (c) Microsoft Corporation.
|
|
7
|
+
|
|
8
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
9
|
+
purpose with or without fee is hereby granted.
|
|
10
|
+
|
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
12
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
13
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
14
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
15
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
16
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
17
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
18
|
+
***************************************************************************** */
|
|
19
|
+
|
|
20
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
21
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
22
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
23
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
24
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
25
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
26
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
31
|
+
var e = new Error(message);
|
|
32
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
exports.__awaiter = __awaiter;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
Copyright (c) Microsoft Corporation.
|
|
3
|
+
|
|
4
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
5
|
+
purpose with or without fee is hereby granted.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
8
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
9
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
10
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
11
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
12
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
13
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
14
|
+
***************************************************************************** */
|
|
15
|
+
|
|
16
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
17
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
18
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
19
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
20
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
21
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
22
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
27
|
+
var e = new Error(message);
|
|
28
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export { __awaiter };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs/ethereum-aa",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.9",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/dynamic-labs/DynamicAuth.git",
|
|
@@ -27,16 +27,17 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@dynamic-labs/sdk-api": "0.0.376",
|
|
30
|
-
"@
|
|
31
|
-
"@
|
|
32
|
-
"@dynamic-labs/
|
|
33
|
-
"@dynamic-labs/
|
|
34
|
-
"@dynamic-labs/
|
|
35
|
-
"@dynamic-labs/
|
|
36
|
-
"@dynamic-labs/wallet-book": "2.0.0-alpha.7",
|
|
37
|
-
"@dynamic-labs/wallet-connector-core": "2.0.0-alpha.7"
|
|
30
|
+
"@dynamic-labs/logger": "2.0.0-alpha.9",
|
|
31
|
+
"@dynamic-labs/types": "2.0.0-alpha.9",
|
|
32
|
+
"@dynamic-labs/utils": "2.0.0-alpha.9",
|
|
33
|
+
"@dynamic-labs/viem-utils": "2.0.0-alpha.9",
|
|
34
|
+
"@dynamic-labs/wallet-book": "2.0.0-alpha.9",
|
|
35
|
+
"@dynamic-labs/wallet-connector-core": "2.0.0-alpha.9"
|
|
38
36
|
},
|
|
39
37
|
"peerDependencies": {
|
|
38
|
+
"@zerodev/presets": "^5.1.4",
|
|
39
|
+
"@zerodev/sdk": "^5.1.7",
|
|
40
|
+
"permissionless": "^0.0.34",
|
|
40
41
|
"viem": "^2.7.6"
|
|
41
42
|
}
|
|
42
43
|
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _tslib = require('../_virtual/_tslib.cjs');
|
|
6
|
+
var presets = require('@zerodev/presets');
|
|
7
|
+
var viem = require('viem');
|
|
8
|
+
var permissionless = require('permissionless');
|
|
9
|
+
var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
|
|
10
|
+
var viemUtils = require('@dynamic-labs/viem-utils');
|
|
11
|
+
var utils = require('@dynamic-labs/utils');
|
|
12
|
+
var fetchChain = require('./utils/fetchChain.cjs');
|
|
13
|
+
var logger = require('./utils/logger.cjs');
|
|
14
|
+
|
|
15
|
+
class ZeroDevConnector extends walletConnectorCore.WalletConnectorBase {
|
|
16
|
+
constructor(opts) {
|
|
17
|
+
var _a;
|
|
18
|
+
super(opts);
|
|
19
|
+
this.connectedChain = 'EVM';
|
|
20
|
+
this.supportedChains = ['ETH', 'EVM'];
|
|
21
|
+
this.isGasSponsorshipDisabled = false;
|
|
22
|
+
this.isEmbeddedWallet = true;
|
|
23
|
+
this.name = 'ZeroDev';
|
|
24
|
+
this.overrideKey = 'zerodev';
|
|
25
|
+
const zeroDevProjectId = (_a = opts.apiProviders.zerodev) === null || _a === void 0 ? void 0 : _a.clientId;
|
|
26
|
+
if (!zeroDevProjectId) {
|
|
27
|
+
throw new Error('Missing ZeroDev project ID provided. Add your ZeroDev project id to your project configuration via the Dynamic Labs dashboard.');
|
|
28
|
+
}
|
|
29
|
+
this.projectId = zeroDevProjectId;
|
|
30
|
+
this._walletUiUtils = opts.walletUiUtils;
|
|
31
|
+
this.evmNetworks = utils.parseEvmNetworks(opts.evmNetworks);
|
|
32
|
+
}
|
|
33
|
+
getEOAConnector() {
|
|
34
|
+
return this.eoaConnector;
|
|
35
|
+
}
|
|
36
|
+
getAccountAbstractionProvider() {
|
|
37
|
+
return this.kernelClient;
|
|
38
|
+
}
|
|
39
|
+
endSession() {
|
|
40
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
localStorage.removeItem(fetchChain.cachedChainIdKey);
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
setEoaConnector(connector) {
|
|
45
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
this.kernelClientDeferredPromise = new utils.DeferredPromise();
|
|
47
|
+
this.eoaConnector = connector;
|
|
48
|
+
const signer = yield this.eoaConnector.getSigner();
|
|
49
|
+
if (!(signer === null || signer === void 0 ? void 0 : signer.account)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const kernelClient = yield presets.createEcdsaKernelAccountClient({
|
|
53
|
+
chain: yield fetchChain.fetchChain(this.projectId),
|
|
54
|
+
paymaster: 'NONE',
|
|
55
|
+
projectId: this.projectId,
|
|
56
|
+
provider: 'STACKUP',
|
|
57
|
+
signer: permissionless.walletClientToSmartAccountSigner(signer),
|
|
58
|
+
});
|
|
59
|
+
utils.wrapMethodWithCallback(kernelClient, 'sendUserOperation', (original, ...args) => {
|
|
60
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
61
|
+
return original(...args);
|
|
62
|
+
});
|
|
63
|
+
this.kernelClient = kernelClient;
|
|
64
|
+
yield this.checkIsProjectChainEnabled();
|
|
65
|
+
this.kernelClientDeferredPromise.resolve();
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
checkIsProjectChainEnabled() {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
71
|
+
const client = yield this.getPublicClient();
|
|
72
|
+
const chainName = (_a = client === null || client === void 0 ? void 0 : client.chain) === null || _a === void 0 ? void 0 : _a.name;
|
|
73
|
+
const chainId = (_b = client === null || client === void 0 ? void 0 : client.chain) === null || _b === void 0 ? void 0 : _b.id;
|
|
74
|
+
const isProjectChainEnabled = this.evmNetworks.some((network) => network.chainId === chainId);
|
|
75
|
+
if (!isProjectChainEnabled) {
|
|
76
|
+
logger.logger.error(`Please make sure to enable ${chainName} (${chainId}) in the Dynamic dashboard (https://app.dynamic.xyz/dashboard/configurations#evm).`);
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
getKernelClientWithSponsorshipValidation() {
|
|
81
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
if (this.kernelClientWithSponsorship) {
|
|
83
|
+
return this.kernelClientWithSponsorship;
|
|
84
|
+
}
|
|
85
|
+
const { eoaConnector } = this;
|
|
86
|
+
if (!eoaConnector)
|
|
87
|
+
throw new utils.DynamicError('No EOA connector');
|
|
88
|
+
const signer = yield eoaConnector.getSigner();
|
|
89
|
+
this.kernelClientWithSponsorship = yield presets.createEcdsaKernelAccountClient({
|
|
90
|
+
chain: yield fetchChain.fetchChain(this.projectId),
|
|
91
|
+
paymaster: 'SPONSOR',
|
|
92
|
+
projectId: this.projectId,
|
|
93
|
+
provider: 'STACKUP',
|
|
94
|
+
signer: permissionless.walletClientToSmartAccountSigner(signer),
|
|
95
|
+
});
|
|
96
|
+
utils.wrapMethodWithCallback(this.kernelClientWithSponsorship, 'sendUserOperation', (original, ...args) => {
|
|
97
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
98
|
+
return original(...args);
|
|
99
|
+
});
|
|
100
|
+
return this.kernelClientWithSponsorship;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
fetchPublicAddress() {
|
|
104
|
+
var _a, _b, _c;
|
|
105
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
106
|
+
yield ((_a = this.kernelClientDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
|
|
107
|
+
return (_c = (_b = this.kernelClient) === null || _b === void 0 ? void 0 : _b.account) === null || _c === void 0 ? void 0 : _c.address;
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
getConnectedAccounts() {
|
|
111
|
+
var _a, _b, _c;
|
|
112
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
113
|
+
yield ((_a = this.kernelClientDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
|
|
114
|
+
return ((_c = (_b = this.kernelClient) === null || _b === void 0 ? void 0 : _b.account) === null || _c === void 0 ? void 0 : _c.address)
|
|
115
|
+
? [yield this.kernelClient.account.address]
|
|
116
|
+
: [];
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
getNetwork() {
|
|
120
|
+
var _a, _b, _c;
|
|
121
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
122
|
+
yield ((_a = this.kernelClientDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
|
|
123
|
+
return (_c = (_b = this.kernelClient) === null || _b === void 0 ? void 0 : _b.chain) === null || _c === void 0 ? void 0 : _c.id;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
getTransport(provider) {
|
|
127
|
+
const transport = viemUtils.confirmationTransport({
|
|
128
|
+
onPersonalSign: ({ message }) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
129
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
130
|
+
return provider.signMessage({
|
|
131
|
+
account: provider.account,
|
|
132
|
+
message,
|
|
133
|
+
});
|
|
134
|
+
}),
|
|
135
|
+
onSendTransaction: ({ transaction }) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
136
|
+
try {
|
|
137
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
138
|
+
const effectiveProvider = this.isGasSponsorshipDisabled
|
|
139
|
+
? provider
|
|
140
|
+
: yield this.getKernelClientWithSponsorshipValidation();
|
|
141
|
+
const response = yield effectiveProvider.sendTransaction(viemUtils.unFormatTransaction(transaction));
|
|
142
|
+
return response;
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
logger.logger.debug(err);
|
|
146
|
+
if (utils.TransactionGasCannotBeSponsoredError.isErrorMessage(err)) {
|
|
147
|
+
throw new utils.TransactionGasCannotBeSponsoredError();
|
|
148
|
+
}
|
|
149
|
+
if (utils.InsufficientFundsError.isErrorMessage(err)) {
|
|
150
|
+
throw new utils.InsufficientFundsError();
|
|
151
|
+
}
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
}),
|
|
155
|
+
onSignTypedData: ({ message }) => _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
156
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
157
|
+
const signTypedData = JSON.parse(message);
|
|
158
|
+
return provider.signTypedData({
|
|
159
|
+
account: provider.account,
|
|
160
|
+
message: signTypedData.message,
|
|
161
|
+
primaryType: signTypedData.primaryType,
|
|
162
|
+
types: signTypedData.types,
|
|
163
|
+
});
|
|
164
|
+
}),
|
|
165
|
+
provider,
|
|
166
|
+
transport: viem.custom(provider),
|
|
167
|
+
walletUiUtils: this._walletUiUtils,
|
|
168
|
+
});
|
|
169
|
+
return transport;
|
|
170
|
+
}
|
|
171
|
+
getWalletClient() {
|
|
172
|
+
const provider = this.kernelClient;
|
|
173
|
+
if (!provider)
|
|
174
|
+
throw new utils.DynamicError('No provider');
|
|
175
|
+
const transport = this.getTransport(provider);
|
|
176
|
+
const walletClient = viem.createWalletClient({
|
|
177
|
+
transport,
|
|
178
|
+
});
|
|
179
|
+
return walletClient;
|
|
180
|
+
}
|
|
181
|
+
getPublicClient() {
|
|
182
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
183
|
+
const provider = this.kernelClient.extend(viem.publicActions);
|
|
184
|
+
if (!provider)
|
|
185
|
+
throw new utils.DynamicError('No provider');
|
|
186
|
+
return provider;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
getSigner() {
|
|
190
|
+
var _a;
|
|
191
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
192
|
+
const provider = this.kernelClient;
|
|
193
|
+
if (!provider)
|
|
194
|
+
throw new utils.DynamicError('No provider');
|
|
195
|
+
const transport = this.getTransport(provider);
|
|
196
|
+
const address = (_a = provider.account) === null || _a === void 0 ? void 0 : _a.address;
|
|
197
|
+
const walletClient = viem.createWalletClient({
|
|
198
|
+
account: address,
|
|
199
|
+
transport,
|
|
200
|
+
});
|
|
201
|
+
return walletClient;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
canSponsorTransactionGas(transaction) {
|
|
205
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
206
|
+
try {
|
|
207
|
+
yield this.getKernelClientWithSponsorshipValidation();
|
|
208
|
+
const userOperation = {
|
|
209
|
+
callData: yield this.kernelClientWithSponsorship.account.encodeCallData({
|
|
210
|
+
data: transaction.data ? transaction.data : '0x',
|
|
211
|
+
to: transaction.to,
|
|
212
|
+
value: viem.isHex(transaction.value)
|
|
213
|
+
? viem.fromHex(transaction.value, 'bigint')
|
|
214
|
+
: transaction.value,
|
|
215
|
+
}),
|
|
216
|
+
};
|
|
217
|
+
const result = yield this.kernelClientWithSponsorship.prepareUserOperationRequest({
|
|
218
|
+
account: this.kernelClientWithSponsorship.account,
|
|
219
|
+
userOperation,
|
|
220
|
+
});
|
|
221
|
+
if (!result)
|
|
222
|
+
return false;
|
|
223
|
+
return result.paymasterAndData !== '0x';
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
logger.logger.debug(err);
|
|
227
|
+
return false;
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
disableGasSponsorshipOnce() {
|
|
232
|
+
this.isGasSponsorshipDisabled = true;
|
|
233
|
+
}
|
|
234
|
+
getBalance() {
|
|
235
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
236
|
+
const rpcClient = this.kernelClient.extend(viem.publicActions);
|
|
237
|
+
if (!rpcClient)
|
|
238
|
+
throw new utils.DynamicError('No RPC client');
|
|
239
|
+
const address = yield this.fetchPublicAddress();
|
|
240
|
+
if (!address)
|
|
241
|
+
return;
|
|
242
|
+
return viem.formatEther(yield rpcClient.getBalance({ address: address }));
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
signMessage(messageToSign) {
|
|
246
|
+
return _tslib.__awaiter(this, void 0, void 0, function* () {
|
|
247
|
+
const client = yield this.getSigner();
|
|
248
|
+
const account = yield this.fetchPublicAddress();
|
|
249
|
+
if (!account || !client)
|
|
250
|
+
return;
|
|
251
|
+
return client.signMessage({
|
|
252
|
+
account: account,
|
|
253
|
+
message: messageToSign,
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
exports.ZeroDevConnector = ZeroDevConnector;
|
|
@@ -14,9 +14,9 @@ type ZeroDevConnectorProps = {
|
|
|
14
14
|
};
|
|
15
15
|
export declare class ZeroDevConnector extends WalletConnectorBase implements IAccountAbstractionWalletConnector {
|
|
16
16
|
projectId: string;
|
|
17
|
-
|
|
17
|
+
kernelClient: KernelAccountClient | undefined;
|
|
18
18
|
eoaConnector: WalletConnector | undefined;
|
|
19
|
-
private
|
|
19
|
+
private kernelClientWithSponsorship;
|
|
20
20
|
connectedChain: Chain;
|
|
21
21
|
supportedChains: Chain[];
|
|
22
22
|
evmNetworks: EvmNetwork[];
|
|
@@ -27,16 +27,17 @@ export declare class ZeroDevConnector extends WalletConnectorBase implements IAc
|
|
|
27
27
|
* This is used to make sure that the provider is set before any other method is called.
|
|
28
28
|
* This is needed because the provider is set asynchronously.
|
|
29
29
|
*/
|
|
30
|
-
private
|
|
30
|
+
private kernelClientDeferredPromise;
|
|
31
31
|
name: string;
|
|
32
32
|
overrideKey: string;
|
|
33
33
|
private _walletUiUtils;
|
|
34
34
|
constructor(opts: ZeroDevConnectorProps);
|
|
35
35
|
getEOAConnector(): WalletConnector | undefined;
|
|
36
36
|
getAccountAbstractionProvider(): KernelAccountClient | undefined;
|
|
37
|
+
endSession(): Promise<void>;
|
|
37
38
|
setEoaConnector(connector: WalletConnector): Promise<void>;
|
|
38
39
|
private checkIsProjectChainEnabled;
|
|
39
|
-
private
|
|
40
|
+
private getKernelClientWithSponsorshipValidation;
|
|
40
41
|
fetchPublicAddress(): Promise<string | undefined>;
|
|
41
42
|
getConnectedAccounts(): Promise<string[]>;
|
|
42
43
|
getNetwork(): Promise<number | undefined>;
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { __awaiter } from '../_virtual/_tslib.js';
|
|
2
|
+
import { createEcdsaKernelAccountClient } from '@zerodev/presets';
|
|
3
|
+
import { custom, createWalletClient, publicActions, isHex, fromHex, formatEther } from 'viem';
|
|
4
|
+
import { walletClientToSmartAccountSigner } from 'permissionless';
|
|
5
|
+
import { WalletConnectorBase } from '@dynamic-labs/wallet-connector-core';
|
|
6
|
+
import { confirmationTransport, unFormatTransaction } from '@dynamic-labs/viem-utils';
|
|
7
|
+
import { parseEvmNetworks, DynamicError, DeferredPromise, wrapMethodWithCallback, TransactionGasCannotBeSponsoredError, InsufficientFundsError } from '@dynamic-labs/utils';
|
|
8
|
+
import { cachedChainIdKey, fetchChain } from './utils/fetchChain.js';
|
|
9
|
+
import { logger } from './utils/logger.js';
|
|
10
|
+
|
|
11
|
+
class ZeroDevConnector extends WalletConnectorBase {
|
|
12
|
+
constructor(opts) {
|
|
13
|
+
var _a;
|
|
14
|
+
super(opts);
|
|
15
|
+
this.connectedChain = 'EVM';
|
|
16
|
+
this.supportedChains = ['ETH', 'EVM'];
|
|
17
|
+
this.isGasSponsorshipDisabled = false;
|
|
18
|
+
this.isEmbeddedWallet = true;
|
|
19
|
+
this.name = 'ZeroDev';
|
|
20
|
+
this.overrideKey = 'zerodev';
|
|
21
|
+
const zeroDevProjectId = (_a = opts.apiProviders.zerodev) === null || _a === void 0 ? void 0 : _a.clientId;
|
|
22
|
+
if (!zeroDevProjectId) {
|
|
23
|
+
throw new Error('Missing ZeroDev project ID provided. Add your ZeroDev project id to your project configuration via the Dynamic Labs dashboard.');
|
|
24
|
+
}
|
|
25
|
+
this.projectId = zeroDevProjectId;
|
|
26
|
+
this._walletUiUtils = opts.walletUiUtils;
|
|
27
|
+
this.evmNetworks = parseEvmNetworks(opts.evmNetworks);
|
|
28
|
+
}
|
|
29
|
+
getEOAConnector() {
|
|
30
|
+
return this.eoaConnector;
|
|
31
|
+
}
|
|
32
|
+
getAccountAbstractionProvider() {
|
|
33
|
+
return this.kernelClient;
|
|
34
|
+
}
|
|
35
|
+
endSession() {
|
|
36
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
37
|
+
localStorage.removeItem(cachedChainIdKey);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
setEoaConnector(connector) {
|
|
41
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
this.kernelClientDeferredPromise = new DeferredPromise();
|
|
43
|
+
this.eoaConnector = connector;
|
|
44
|
+
const signer = yield this.eoaConnector.getSigner();
|
|
45
|
+
if (!(signer === null || signer === void 0 ? void 0 : signer.account)) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const kernelClient = yield createEcdsaKernelAccountClient({
|
|
49
|
+
chain: yield fetchChain(this.projectId),
|
|
50
|
+
paymaster: 'NONE',
|
|
51
|
+
projectId: this.projectId,
|
|
52
|
+
provider: 'STACKUP',
|
|
53
|
+
signer: walletClientToSmartAccountSigner(signer),
|
|
54
|
+
});
|
|
55
|
+
wrapMethodWithCallback(kernelClient, 'sendUserOperation', (original, ...args) => {
|
|
56
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
57
|
+
return original(...args);
|
|
58
|
+
});
|
|
59
|
+
this.kernelClient = kernelClient;
|
|
60
|
+
yield this.checkIsProjectChainEnabled();
|
|
61
|
+
this.kernelClientDeferredPromise.resolve();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
checkIsProjectChainEnabled() {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
const client = yield this.getPublicClient();
|
|
68
|
+
const chainName = (_a = client === null || client === void 0 ? void 0 : client.chain) === null || _a === void 0 ? void 0 : _a.name;
|
|
69
|
+
const chainId = (_b = client === null || client === void 0 ? void 0 : client.chain) === null || _b === void 0 ? void 0 : _b.id;
|
|
70
|
+
const isProjectChainEnabled = this.evmNetworks.some((network) => network.chainId === chainId);
|
|
71
|
+
if (!isProjectChainEnabled) {
|
|
72
|
+
logger.error(`Please make sure to enable ${chainName} (${chainId}) in the Dynamic dashboard (https://app.dynamic.xyz/dashboard/configurations#evm).`);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
getKernelClientWithSponsorshipValidation() {
|
|
77
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
78
|
+
if (this.kernelClientWithSponsorship) {
|
|
79
|
+
return this.kernelClientWithSponsorship;
|
|
80
|
+
}
|
|
81
|
+
const { eoaConnector } = this;
|
|
82
|
+
if (!eoaConnector)
|
|
83
|
+
throw new DynamicError('No EOA connector');
|
|
84
|
+
const signer = yield eoaConnector.getSigner();
|
|
85
|
+
this.kernelClientWithSponsorship = yield createEcdsaKernelAccountClient({
|
|
86
|
+
chain: yield fetchChain(this.projectId),
|
|
87
|
+
paymaster: 'SPONSOR',
|
|
88
|
+
projectId: this.projectId,
|
|
89
|
+
provider: 'STACKUP',
|
|
90
|
+
signer: walletClientToSmartAccountSigner(signer),
|
|
91
|
+
});
|
|
92
|
+
wrapMethodWithCallback(this.kernelClientWithSponsorship, 'sendUserOperation', (original, ...args) => {
|
|
93
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
94
|
+
return original(...args);
|
|
95
|
+
});
|
|
96
|
+
return this.kernelClientWithSponsorship;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
fetchPublicAddress() {
|
|
100
|
+
var _a, _b, _c;
|
|
101
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
102
|
+
yield ((_a = this.kernelClientDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
|
|
103
|
+
return (_c = (_b = this.kernelClient) === null || _b === void 0 ? void 0 : _b.account) === null || _c === void 0 ? void 0 : _c.address;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
getConnectedAccounts() {
|
|
107
|
+
var _a, _b, _c;
|
|
108
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
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)
|
|
111
|
+
? [yield this.kernelClient.account.address]
|
|
112
|
+
: [];
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
getNetwork() {
|
|
116
|
+
var _a, _b, _c;
|
|
117
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
+
yield ((_a = this.kernelClientDeferredPromise) === null || _a === void 0 ? void 0 : _a.promise);
|
|
119
|
+
return (_c = (_b = this.kernelClient) === null || _b === void 0 ? void 0 : _b.chain) === null || _c === void 0 ? void 0 : _c.id;
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
getTransport(provider) {
|
|
123
|
+
const transport = confirmationTransport({
|
|
124
|
+
onPersonalSign: ({ message }) => __awaiter(this, void 0, void 0, function* () {
|
|
125
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
126
|
+
return provider.signMessage({
|
|
127
|
+
account: provider.account,
|
|
128
|
+
message,
|
|
129
|
+
});
|
|
130
|
+
}),
|
|
131
|
+
onSendTransaction: ({ transaction }) => __awaiter(this, void 0, void 0, function* () {
|
|
132
|
+
try {
|
|
133
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
134
|
+
const effectiveProvider = this.isGasSponsorshipDisabled
|
|
135
|
+
? provider
|
|
136
|
+
: yield this.getKernelClientWithSponsorshipValidation();
|
|
137
|
+
const response = yield effectiveProvider.sendTransaction(unFormatTransaction(transaction));
|
|
138
|
+
return response;
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
logger.debug(err);
|
|
142
|
+
if (TransactionGasCannotBeSponsoredError.isErrorMessage(err)) {
|
|
143
|
+
throw new TransactionGasCannotBeSponsoredError();
|
|
144
|
+
}
|
|
145
|
+
if (InsufficientFundsError.isErrorMessage(err)) {
|
|
146
|
+
throw new InsufficientFundsError();
|
|
147
|
+
}
|
|
148
|
+
throw err;
|
|
149
|
+
}
|
|
150
|
+
}),
|
|
151
|
+
onSignTypedData: ({ message }) => __awaiter(this, void 0, void 0, function* () {
|
|
152
|
+
this._walletUiUtils.disabledConfirmationOnce();
|
|
153
|
+
const signTypedData = JSON.parse(message);
|
|
154
|
+
return provider.signTypedData({
|
|
155
|
+
account: provider.account,
|
|
156
|
+
message: signTypedData.message,
|
|
157
|
+
primaryType: signTypedData.primaryType,
|
|
158
|
+
types: signTypedData.types,
|
|
159
|
+
});
|
|
160
|
+
}),
|
|
161
|
+
provider,
|
|
162
|
+
transport: custom(provider),
|
|
163
|
+
walletUiUtils: this._walletUiUtils,
|
|
164
|
+
});
|
|
165
|
+
return transport;
|
|
166
|
+
}
|
|
167
|
+
getWalletClient() {
|
|
168
|
+
const provider = this.kernelClient;
|
|
169
|
+
if (!provider)
|
|
170
|
+
throw new DynamicError('No provider');
|
|
171
|
+
const transport = this.getTransport(provider);
|
|
172
|
+
const walletClient = createWalletClient({
|
|
173
|
+
transport,
|
|
174
|
+
});
|
|
175
|
+
return walletClient;
|
|
176
|
+
}
|
|
177
|
+
getPublicClient() {
|
|
178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
const provider = this.kernelClient.extend(publicActions);
|
|
180
|
+
if (!provider)
|
|
181
|
+
throw new DynamicError('No provider');
|
|
182
|
+
return provider;
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
getSigner() {
|
|
186
|
+
var _a;
|
|
187
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
188
|
+
const provider = this.kernelClient;
|
|
189
|
+
if (!provider)
|
|
190
|
+
throw new DynamicError('No provider');
|
|
191
|
+
const transport = this.getTransport(provider);
|
|
192
|
+
const address = (_a = provider.account) === null || _a === void 0 ? void 0 : _a.address;
|
|
193
|
+
const walletClient = createWalletClient({
|
|
194
|
+
account: address,
|
|
195
|
+
transport,
|
|
196
|
+
});
|
|
197
|
+
return walletClient;
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
canSponsorTransactionGas(transaction) {
|
|
201
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
202
|
+
try {
|
|
203
|
+
yield this.getKernelClientWithSponsorshipValidation();
|
|
204
|
+
const userOperation = {
|
|
205
|
+
callData: yield this.kernelClientWithSponsorship.account.encodeCallData({
|
|
206
|
+
data: transaction.data ? transaction.data : '0x',
|
|
207
|
+
to: transaction.to,
|
|
208
|
+
value: isHex(transaction.value)
|
|
209
|
+
? fromHex(transaction.value, 'bigint')
|
|
210
|
+
: transaction.value,
|
|
211
|
+
}),
|
|
212
|
+
};
|
|
213
|
+
const result = yield this.kernelClientWithSponsorship.prepareUserOperationRequest({
|
|
214
|
+
account: this.kernelClientWithSponsorship.account,
|
|
215
|
+
userOperation,
|
|
216
|
+
});
|
|
217
|
+
if (!result)
|
|
218
|
+
return false;
|
|
219
|
+
return result.paymasterAndData !== '0x';
|
|
220
|
+
}
|
|
221
|
+
catch (err) {
|
|
222
|
+
logger.debug(err);
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
disableGasSponsorshipOnce() {
|
|
228
|
+
this.isGasSponsorshipDisabled = true;
|
|
229
|
+
}
|
|
230
|
+
getBalance() {
|
|
231
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
232
|
+
const rpcClient = this.kernelClient.extend(publicActions);
|
|
233
|
+
if (!rpcClient)
|
|
234
|
+
throw new DynamicError('No RPC client');
|
|
235
|
+
const address = yield this.fetchPublicAddress();
|
|
236
|
+
if (!address)
|
|
237
|
+
return;
|
|
238
|
+
return formatEther(yield rpcClient.getBalance({ address: address }));
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
signMessage(messageToSign) {
|
|
242
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
243
|
+
const client = yield this.getSigner();
|
|
244
|
+
const account = yield this.fetchPublicAddress();
|
|
245
|
+
if (!account || !client)
|
|
246
|
+
return;
|
|
247
|
+
return client.signMessage({
|
|
248
|
+
account: account,
|
|
249
|
+
message: messageToSign,
|
|
250
|
+
});
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export { ZeroDevConnector };
|
package/src/index.cjs
CHANGED
|
@@ -2,15 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var
|
|
5
|
+
var ZeroDevConnector = require('./ZeroDevConnector.cjs');
|
|
6
6
|
var ethereumAa = require('./ethereum-aa.cjs');
|
|
7
7
|
var isZeroDevConnector = require('./utils/isZeroDevConnector.cjs');
|
|
8
8
|
|
|
9
9
|
const ZeroDevSmartWalletConnectors = (props) => {
|
|
10
10
|
var _a;
|
|
11
11
|
if ((_a = props.apiProviders) === null || _a === void 0 ? void 0 : _a.zerodev) {
|
|
12
|
-
|
|
13
|
-
return [];
|
|
12
|
+
return [ZeroDevConnector.ZeroDevConnector];
|
|
14
13
|
}
|
|
15
14
|
return [];
|
|
16
15
|
};
|
package/src/index.js
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ZeroDevConnector } from './ZeroDevConnector.js';
|
|
2
2
|
export { EthereumAaConnector } from './ethereum-aa.js';
|
|
3
3
|
export { isZeroDevConnector } from './utils/isZeroDevConnector.js';
|
|
4
4
|
|
|
5
5
|
const ZeroDevSmartWalletConnectors = (props) => {
|
|
6
6
|
var _a;
|
|
7
7
|
if ((_a = props.apiProviders) === null || _a === void 0 ? void 0 : _a.zerodev) {
|
|
8
|
-
|
|
9
|
-
return [];
|
|
8
|
+
return [ZeroDevConnector];
|
|
10
9
|
}
|
|
11
10
|
return [];
|
|
12
11
|
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var _tslib = require('../../_virtual/_tslib.cjs');
|
|
6
|
+
var chains = require('viem/chains');
|
|
7
|
+
var logger = require('./logger.cjs');
|
|
8
|
+
|
|
9
|
+
function _interopNamespace(e) {
|
|
10
|
+
if (e && e.__esModule) return e;
|
|
11
|
+
var n = Object.create(null);
|
|
12
|
+
if (e) {
|
|
13
|
+
Object.keys(e).forEach(function (k) {
|
|
14
|
+
if (k !== 'default') {
|
|
15
|
+
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
16
|
+
Object.defineProperty(n, k, d.get ? d : {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
get: function () { return e[k]; }
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
n["default"] = e;
|
|
24
|
+
return Object.freeze(n);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
var chains__namespace = /*#__PURE__*/_interopNamespace(chains);
|
|
28
|
+
|
|
29
|
+
const chainsMap = Object.values(chains__namespace).reduce((acc, chain) => (Object.assign(Object.assign({}, acc), { [chain.id]: chain })), {});
|
|
30
|
+
const cachedChainIdKey = 'dynamic_zd_chain_id';
|
|
31
|
+
const fetchChain = (projectId) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
|
|
32
|
+
try {
|
|
33
|
+
const cachedChainId = localStorage.getItem(cachedChainIdKey);
|
|
34
|
+
if (cachedChainId) {
|
|
35
|
+
return chainsMap[cachedChainId];
|
|
36
|
+
}
|
|
37
|
+
const response = yield (yield fetch(`https://prod-api.zerodev.app/projects/${projectId}`)).json();
|
|
38
|
+
localStorage.setItem(cachedChainIdKey, response.chainId);
|
|
39
|
+
return chainsMap[response.chainId];
|
|
40
|
+
}
|
|
41
|
+
catch (err) {
|
|
42
|
+
logger.logger.error('Failed to fetch ZeroDev project settings from ZeroDev API ' +
|
|
43
|
+
'This is needed to fetch the chain id so that we know which chain the smart contract is on');
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
exports.cachedChainIdKey = cachedChainIdKey;
|
|
49
|
+
exports.fetchChain = fetchChain;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { __awaiter } from '../../_virtual/_tslib.js';
|
|
2
|
+
import * as chains from 'viem/chains';
|
|
3
|
+
import { logger } from './logger.js';
|
|
4
|
+
|
|
5
|
+
const chainsMap = Object.values(chains).reduce((acc, chain) => (Object.assign(Object.assign({}, acc), { [chain.id]: chain })), {});
|
|
6
|
+
const cachedChainIdKey = 'dynamic_zd_chain_id';
|
|
7
|
+
const fetchChain = (projectId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
8
|
+
try {
|
|
9
|
+
const cachedChainId = localStorage.getItem(cachedChainIdKey);
|
|
10
|
+
if (cachedChainId) {
|
|
11
|
+
return chainsMap[cachedChainId];
|
|
12
|
+
}
|
|
13
|
+
const response = yield (yield fetch(`https://prod-api.zerodev.app/projects/${projectId}`)).json();
|
|
14
|
+
localStorage.setItem(cachedChainIdKey, response.chainId);
|
|
15
|
+
return chainsMap[response.chainId];
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
logger.error('Failed to fetch ZeroDev project settings from ZeroDev API ' +
|
|
19
|
+
'This is needed to fetch the chain id so that we know which chain the smart contract is on');
|
|
20
|
+
throw err;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
export { cachedChainIdKey, fetchChain };
|