@dynamic-labs-wallet/evm 0.0.0-beta-191.1

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/index.cjs.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/index";
package/index.cjs.js ADDED
@@ -0,0 +1,328 @@
1
+ 'use strict';
2
+
3
+ var browser = require('@dynamic-labs-wallet/browser');
4
+ var viem = require('viem');
5
+ var chains = require('viem/chains');
6
+
7
+ function _extends() {
8
+ _extends = Object.assign || function assign(target) {
9
+ for(var i = 1; i < arguments.length; i++){
10
+ var source = arguments[i];
11
+ for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
12
+ }
13
+ return target;
14
+ };
15
+ return _extends.apply(this, arguments);
16
+ }
17
+
18
+ const EVM_SIGN_MESSAGE_PREFIX = `\x19Ethereum Signed Message:\n`;
19
+
20
+ const formatEVMMessage = (message_)=>{
21
+ const message = (()=>{
22
+ if (typeof message_ === 'string') return viem.stringToHex(message_);
23
+ if (typeof message_.raw === 'string') return message_.raw;
24
+ return viem.bytesToHex(message_.raw);
25
+ })();
26
+ const prefix = viem.stringToHex(`${EVM_SIGN_MESSAGE_PREFIX}${viem.size(message)}`);
27
+ return viem.concat([
28
+ prefix,
29
+ message
30
+ ]);
31
+ };
32
+ const serializeECDSASignature = (signature)=>{
33
+ return viem.serializeSignature({
34
+ r: `0x${Buffer.from(signature.r).toString('hex')}`,
35
+ s: `0x${Buffer.from(signature.s).toString('hex')}`,
36
+ v: BigInt(signature.v)
37
+ });
38
+ };
39
+
40
+ const checkRawPublicKeyInstance = (rawPublicKey)=>{
41
+ if (!(rawPublicKey instanceof browser.EcdsaPublicKey)) {
42
+ throw new Error('Invalid raw public key');
43
+ }
44
+ };
45
+
46
+ class DynamicEvmWalletClient extends browser.DynamicWalletClient {
47
+ createViemPublicClient({ chain, rpcUrl }) {
48
+ return viem.createPublicClient({
49
+ chain,
50
+ transport: viem.http(rpcUrl)
51
+ });
52
+ }
53
+ async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
54
+ try {
55
+ // Create a promise that will resolve when the ceremony is complete
56
+ let ceremonyCeremonyCompleteResolver;
57
+ const ceremonyCompletePromise = new Promise((resolve)=>{
58
+ ceremonyCeremonyCompleteResolver = resolve;
59
+ });
60
+ // Generate key shares for given threshold signature scheme (TSS)
61
+ const { rawPublicKey, clientKeyShares } = await this.keyGen({
62
+ chainName: this.chainName,
63
+ thresholdSignatureScheme,
64
+ onError: (error)=>{
65
+ this.logger.error(browser.ERROR_CREATE_WALLET_ACCOUNT, error);
66
+ onError == null ? void 0 : onError(error);
67
+ },
68
+ onCeremonyComplete: (accountAddress, walletId)=>{
69
+ // update wallet map
70
+ const checksumAddress = viem.getAddress(accountAddress);
71
+ this.walletMap[checksumAddress] = _extends({}, this.walletMap[checksumAddress] || {}, {
72
+ accountAddress: checksumAddress,
73
+ walletId,
74
+ chainName: this.chainName,
75
+ thresholdSignatureScheme,
76
+ clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
77
+ });
78
+ this.logger.debug('walletMap updated for wallet', {
79
+ context: {
80
+ accountAddress,
81
+ walletId,
82
+ walletMap: this.walletMap
83
+ }
84
+ });
85
+ // Resolve the promise when ceremony is complete
86
+ ceremonyCeremonyCompleteResolver(undefined);
87
+ }
88
+ });
89
+ // Wait for the ceremony to complete before proceeding
90
+ await ceremonyCompletePromise;
91
+ if (!rawPublicKey || !clientKeyShares) {
92
+ throw new Error(browser.ERROR_KEYGEN_FAILED);
93
+ }
94
+ checkRawPublicKeyInstance(rawPublicKey);
95
+ const { accountAddress, publicKeyHex } = await this.deriveAccountAddress({
96
+ rawPublicKey: rawPublicKey
97
+ });
98
+ // Update client key shares in wallet map
99
+ await this.setClientKeySharesToLocalStorage({
100
+ accountAddress,
101
+ clientKeyShares,
102
+ overwriteOrMerge: 'overwrite'
103
+ });
104
+ await this.storeEncryptedBackupByWalletWithRetry({
105
+ accountAddress,
106
+ clientKeyShares,
107
+ password,
108
+ signedSessionId
109
+ });
110
+ return {
111
+ accountAddress,
112
+ rawPublicKey,
113
+ publicKeyHex
114
+ };
115
+ } catch (error) {
116
+ this.logger.error(browser.ERROR_CREATE_WALLET_ACCOUNT, error);
117
+ throw new Error(browser.ERROR_CREATE_WALLET_ACCOUNT);
118
+ }
119
+ }
120
+ async signMessage({ message, accountAddress, password = undefined, signedSessionId }) {
121
+ await this.verifyPassword({
122
+ accountAddress,
123
+ password,
124
+ walletOperation: browser.WalletOperation.SIGN_MESSAGE,
125
+ signedSessionId
126
+ });
127
+ try {
128
+ if (!accountAddress) {
129
+ throw new Error(browser.ERROR_ACCOUNT_ADDRESS_REQUIRED);
130
+ }
131
+ // Format the message for EVM signing
132
+ const formattedMessage = formatEVMMessage(message);
133
+ // Sign the message using MPC
134
+ const signatureEcdsa = await this.sign({
135
+ message: formattedMessage,
136
+ accountAddress: accountAddress,
137
+ chainName: this.chainName,
138
+ password,
139
+ signedSessionId
140
+ });
141
+ // Serialize the signature
142
+ const serializedSignature = serializeECDSASignature(signatureEcdsa);
143
+ return serializedSignature;
144
+ } catch (error) {
145
+ this.logger.error(browser.ERROR_SIGN_MESSAGE, error);
146
+ throw new Error(browser.ERROR_SIGN_MESSAGE);
147
+ }
148
+ }
149
+ async verifyMessageSignature({ accountAddress, message, signature }) {
150
+ try {
151
+ // Verify the signature using the public client
152
+ const publicClient = this.createViemPublicClient({
153
+ chain: chains.mainnet
154
+ });
155
+ const verified = await publicClient.verifyMessage({
156
+ address: accountAddress,
157
+ message,
158
+ signature: signature
159
+ });
160
+ return verified;
161
+ } catch (error) {
162
+ this.logger.error(browser.ERROR_VERIFY_MESSAGE_SIGNATURE, error);
163
+ throw new Error(browser.ERROR_VERIFY_MESSAGE_SIGNATURE);
164
+ }
165
+ }
166
+ async signTransaction({ senderAddress, transaction, password = undefined, signedSessionId }) {
167
+ await this.verifyPassword({
168
+ accountAddress: senderAddress,
169
+ password,
170
+ walletOperation: browser.WalletOperation.SIGN_TRANSACTION,
171
+ signedSessionId
172
+ });
173
+ const serializedTx = viem.serializeTransaction(transaction);
174
+ const serializedTxBytes = Uint8Array.from(Buffer.from(serializedTx.slice(2), 'hex'));
175
+ if (!(serializedTxBytes instanceof Uint8Array)) {
176
+ throw new Error('Invalid serializedTxBytes');
177
+ }
178
+ // Get signature using MPC (this will coordinate with server party)
179
+ const signatureEcdsa = await this.sign({
180
+ message: serializedTxBytes,
181
+ accountAddress: senderAddress,
182
+ chainName: this.chainName,
183
+ password,
184
+ signedSessionId
185
+ });
186
+ if (!('r' in signatureEcdsa && 's' in signatureEcdsa && 'v' in signatureEcdsa)) {
187
+ throw new Error('Invalid signature format returned from MPC signing');
188
+ }
189
+ try {
190
+ const r = `0x${Buffer.from(signatureEcdsa.r).toString('hex')}`;
191
+ const s = `0x${Buffer.from(signatureEcdsa.s).toString('hex')}`;
192
+ const v = BigInt(signatureEcdsa.v);
193
+ const signedTx = _extends({}, transaction, {
194
+ r: r,
195
+ s: s,
196
+ v: v
197
+ });
198
+ const serializedSignedTx = viem.serializeTransaction(signedTx);
199
+ return serializedSignedTx;
200
+ } catch (error) {
201
+ this.logger.error('Error signing transaction:', error);
202
+ throw error;
203
+ }
204
+ }
205
+ deriveAccountAddress({ rawPublicKey }) {
206
+ const serializedUncompressed = rawPublicKey.serializeUncompressed();
207
+ const firstByteRemoved = serializedUncompressed.slice(1);
208
+ const hashed = browser.MessageHash.keccak256(firstByteRemoved).bytes;
209
+ const lastTwentyBytes = hashed.slice(-20);
210
+ const accountAddress = '0x' + Buffer.from(lastTwentyBytes).toString('hex');
211
+ const publicKeyHex = rawPublicKey.pubKeyAsHex();
212
+ return {
213
+ accountAddress: viem.getAddress(accountAddress),
214
+ publicKeyHex
215
+ };
216
+ }
217
+ async exportPrivateKey({ accountAddress, password = undefined, signedSessionId }) {
218
+ await this.verifyPassword({
219
+ accountAddress,
220
+ password,
221
+ walletOperation: browser.WalletOperation.EXPORT_PRIVATE_KEY,
222
+ signedSessionId
223
+ });
224
+ const { derivedPrivateKey } = await this.exportKey({
225
+ accountAddress,
226
+ chainName: this.chainName,
227
+ password,
228
+ signedSessionId
229
+ });
230
+ return derivedPrivateKey;
231
+ }
232
+ async offlineExportPrivateKey({ keyShares, derivationPath }) {
233
+ const { derivedPrivateKey } = await this.offlineExportKey({
234
+ chainName: this.chainName,
235
+ keyShares,
236
+ derivationPath
237
+ });
238
+ return {
239
+ derivedPrivateKey
240
+ };
241
+ }
242
+ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
243
+ try {
244
+ let ceremonyCeremonyCompleteResolver;
245
+ const ceremonyCompletePromise = new Promise((resolve)=>{
246
+ ceremonyCeremonyCompleteResolver = resolve;
247
+ });
248
+ //remove 0x if it exists
249
+ const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey;
250
+ // TODO: validate private key for EVM
251
+ const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
252
+ chainName,
253
+ privateKey: formattedPrivateKey,
254
+ thresholdSignatureScheme,
255
+ onError: (error)=>{
256
+ this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
257
+ onError == null ? void 0 : onError(error);
258
+ },
259
+ onCeremonyComplete: (accountAddress, walletId)=>{
260
+ // update wallet map
261
+ const checksumAddress = viem.getAddress(accountAddress);
262
+ this.walletMap[checksumAddress] = _extends({}, this.walletMap[checksumAddress] || {}, {
263
+ accountAddress: checksumAddress,
264
+ walletId,
265
+ chainName: this.chainName,
266
+ thresholdSignatureScheme,
267
+ clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
268
+ });
269
+ this.logger.debug('walletMap updated for wallet', {
270
+ context: {
271
+ accountAddress,
272
+ walletId,
273
+ walletMap: this.walletMap
274
+ }
275
+ });
276
+ ceremonyCeremonyCompleteResolver(undefined);
277
+ }
278
+ });
279
+ // Wait for the ceremony to complete before proceeding
280
+ await ceremonyCompletePromise;
281
+ if (!rawPublicKey || !clientKeyShares) {
282
+ throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
283
+ }
284
+ checkRawPublicKeyInstance(rawPublicKey);
285
+ const { accountAddress, publicKeyHex } = await this.deriveAccountAddress({
286
+ rawPublicKey: rawPublicKey
287
+ });
288
+ // Update client key shares in wallet map
289
+ await this.setClientKeySharesToLocalStorage({
290
+ accountAddress,
291
+ clientKeyShares,
292
+ overwriteOrMerge: 'overwrite'
293
+ });
294
+ await this.storeEncryptedBackupByWalletWithRetry({
295
+ accountAddress,
296
+ clientKeyShares,
297
+ password,
298
+ signedSessionId
299
+ });
300
+ return {
301
+ accountAddress,
302
+ rawPublicKey,
303
+ publicKeyHex
304
+ };
305
+ } catch (error) {
306
+ this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
307
+ throw error;
308
+ }
309
+ }
310
+ async getEvmWallets() {
311
+ const wallets = await this.getWallets();
312
+ const evmWallets = wallets.filter((wallet)=>wallet.chainName === 'eip155');
313
+ return evmWallets;
314
+ }
315
+ constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, baseClientRelayApiUrl }){
316
+ super({
317
+ environmentId,
318
+ authToken,
319
+ baseApiUrl,
320
+ baseMPCRelayApiUrl,
321
+ storageKey,
322
+ debug,
323
+ baseClientRelayApiUrl
324
+ }), this.chainName = 'EVM';
325
+ }
326
+ }
327
+
328
+ exports.DynamicEvmWalletClient = DynamicEvmWalletClient;
package/index.esm.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./src/index";
package/index.esm.js ADDED
@@ -0,0 +1,326 @@
1
+ import { EcdsaPublicKey, DynamicWalletClient, getClientKeyShareBackupInfo, ERROR_CREATE_WALLET_ACCOUNT, ERROR_KEYGEN_FAILED, WalletOperation, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_SIGN_MESSAGE, ERROR_VERIFY_MESSAGE_SIGNATURE, MessageHash, ERROR_IMPORT_PRIVATE_KEY } from '@dynamic-labs-wallet/browser';
2
+ import { stringToHex, bytesToHex, size, concat, serializeSignature, createPublicClient, http, getAddress, serializeTransaction } from 'viem';
3
+ import { mainnet } from 'viem/chains';
4
+
5
+ function _extends() {
6
+ _extends = Object.assign || function assign(target) {
7
+ for(var i = 1; i < arguments.length; i++){
8
+ var source = arguments[i];
9
+ for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
10
+ }
11
+ return target;
12
+ };
13
+ return _extends.apply(this, arguments);
14
+ }
15
+
16
+ const EVM_SIGN_MESSAGE_PREFIX = `\x19Ethereum Signed Message:\n`;
17
+
18
+ const formatEVMMessage = (message_)=>{
19
+ const message = (()=>{
20
+ if (typeof message_ === 'string') return stringToHex(message_);
21
+ if (typeof message_.raw === 'string') return message_.raw;
22
+ return bytesToHex(message_.raw);
23
+ })();
24
+ const prefix = stringToHex(`${EVM_SIGN_MESSAGE_PREFIX}${size(message)}`);
25
+ return concat([
26
+ prefix,
27
+ message
28
+ ]);
29
+ };
30
+ const serializeECDSASignature = (signature)=>{
31
+ return serializeSignature({
32
+ r: `0x${Buffer.from(signature.r).toString('hex')}`,
33
+ s: `0x${Buffer.from(signature.s).toString('hex')}`,
34
+ v: BigInt(signature.v)
35
+ });
36
+ };
37
+
38
+ const checkRawPublicKeyInstance = (rawPublicKey)=>{
39
+ if (!(rawPublicKey instanceof EcdsaPublicKey)) {
40
+ throw new Error('Invalid raw public key');
41
+ }
42
+ };
43
+
44
+ class DynamicEvmWalletClient extends DynamicWalletClient {
45
+ createViemPublicClient({ chain, rpcUrl }) {
46
+ return createPublicClient({
47
+ chain,
48
+ transport: http(rpcUrl)
49
+ });
50
+ }
51
+ async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
52
+ try {
53
+ // Create a promise that will resolve when the ceremony is complete
54
+ let ceremonyCeremonyCompleteResolver;
55
+ const ceremonyCompletePromise = new Promise((resolve)=>{
56
+ ceremonyCeremonyCompleteResolver = resolve;
57
+ });
58
+ // Generate key shares for given threshold signature scheme (TSS)
59
+ const { rawPublicKey, clientKeyShares } = await this.keyGen({
60
+ chainName: this.chainName,
61
+ thresholdSignatureScheme,
62
+ onError: (error)=>{
63
+ this.logger.error(ERROR_CREATE_WALLET_ACCOUNT, error);
64
+ onError == null ? void 0 : onError(error);
65
+ },
66
+ onCeremonyComplete: (accountAddress, walletId)=>{
67
+ // update wallet map
68
+ const checksumAddress = getAddress(accountAddress);
69
+ this.walletMap[checksumAddress] = _extends({}, this.walletMap[checksumAddress] || {}, {
70
+ accountAddress: checksumAddress,
71
+ walletId,
72
+ chainName: this.chainName,
73
+ thresholdSignatureScheme,
74
+ clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
75
+ });
76
+ this.logger.debug('walletMap updated for wallet', {
77
+ context: {
78
+ accountAddress,
79
+ walletId,
80
+ walletMap: this.walletMap
81
+ }
82
+ });
83
+ // Resolve the promise when ceremony is complete
84
+ ceremonyCeremonyCompleteResolver(undefined);
85
+ }
86
+ });
87
+ // Wait for the ceremony to complete before proceeding
88
+ await ceremonyCompletePromise;
89
+ if (!rawPublicKey || !clientKeyShares) {
90
+ throw new Error(ERROR_KEYGEN_FAILED);
91
+ }
92
+ checkRawPublicKeyInstance(rawPublicKey);
93
+ const { accountAddress, publicKeyHex } = await this.deriveAccountAddress({
94
+ rawPublicKey: rawPublicKey
95
+ });
96
+ // Update client key shares in wallet map
97
+ await this.setClientKeySharesToLocalStorage({
98
+ accountAddress,
99
+ clientKeyShares,
100
+ overwriteOrMerge: 'overwrite'
101
+ });
102
+ await this.storeEncryptedBackupByWalletWithRetry({
103
+ accountAddress,
104
+ clientKeyShares,
105
+ password,
106
+ signedSessionId
107
+ });
108
+ return {
109
+ accountAddress,
110
+ rawPublicKey,
111
+ publicKeyHex
112
+ };
113
+ } catch (error) {
114
+ this.logger.error(ERROR_CREATE_WALLET_ACCOUNT, error);
115
+ throw new Error(ERROR_CREATE_WALLET_ACCOUNT);
116
+ }
117
+ }
118
+ async signMessage({ message, accountAddress, password = undefined, signedSessionId }) {
119
+ await this.verifyPassword({
120
+ accountAddress,
121
+ password,
122
+ walletOperation: WalletOperation.SIGN_MESSAGE,
123
+ signedSessionId
124
+ });
125
+ try {
126
+ if (!accountAddress) {
127
+ throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
128
+ }
129
+ // Format the message for EVM signing
130
+ const formattedMessage = formatEVMMessage(message);
131
+ // Sign the message using MPC
132
+ const signatureEcdsa = await this.sign({
133
+ message: formattedMessage,
134
+ accountAddress: accountAddress,
135
+ chainName: this.chainName,
136
+ password,
137
+ signedSessionId
138
+ });
139
+ // Serialize the signature
140
+ const serializedSignature = serializeECDSASignature(signatureEcdsa);
141
+ return serializedSignature;
142
+ } catch (error) {
143
+ this.logger.error(ERROR_SIGN_MESSAGE, error);
144
+ throw new Error(ERROR_SIGN_MESSAGE);
145
+ }
146
+ }
147
+ async verifyMessageSignature({ accountAddress, message, signature }) {
148
+ try {
149
+ // Verify the signature using the public client
150
+ const publicClient = this.createViemPublicClient({
151
+ chain: mainnet
152
+ });
153
+ const verified = await publicClient.verifyMessage({
154
+ address: accountAddress,
155
+ message,
156
+ signature: signature
157
+ });
158
+ return verified;
159
+ } catch (error) {
160
+ this.logger.error(ERROR_VERIFY_MESSAGE_SIGNATURE, error);
161
+ throw new Error(ERROR_VERIFY_MESSAGE_SIGNATURE);
162
+ }
163
+ }
164
+ async signTransaction({ senderAddress, transaction, password = undefined, signedSessionId }) {
165
+ await this.verifyPassword({
166
+ accountAddress: senderAddress,
167
+ password,
168
+ walletOperation: WalletOperation.SIGN_TRANSACTION,
169
+ signedSessionId
170
+ });
171
+ const serializedTx = serializeTransaction(transaction);
172
+ const serializedTxBytes = Uint8Array.from(Buffer.from(serializedTx.slice(2), 'hex'));
173
+ if (!(serializedTxBytes instanceof Uint8Array)) {
174
+ throw new Error('Invalid serializedTxBytes');
175
+ }
176
+ // Get signature using MPC (this will coordinate with server party)
177
+ const signatureEcdsa = await this.sign({
178
+ message: serializedTxBytes,
179
+ accountAddress: senderAddress,
180
+ chainName: this.chainName,
181
+ password,
182
+ signedSessionId
183
+ });
184
+ if (!('r' in signatureEcdsa && 's' in signatureEcdsa && 'v' in signatureEcdsa)) {
185
+ throw new Error('Invalid signature format returned from MPC signing');
186
+ }
187
+ try {
188
+ const r = `0x${Buffer.from(signatureEcdsa.r).toString('hex')}`;
189
+ const s = `0x${Buffer.from(signatureEcdsa.s).toString('hex')}`;
190
+ const v = BigInt(signatureEcdsa.v);
191
+ const signedTx = _extends({}, transaction, {
192
+ r: r,
193
+ s: s,
194
+ v: v
195
+ });
196
+ const serializedSignedTx = serializeTransaction(signedTx);
197
+ return serializedSignedTx;
198
+ } catch (error) {
199
+ this.logger.error('Error signing transaction:', error);
200
+ throw error;
201
+ }
202
+ }
203
+ deriveAccountAddress({ rawPublicKey }) {
204
+ const serializedUncompressed = rawPublicKey.serializeUncompressed();
205
+ const firstByteRemoved = serializedUncompressed.slice(1);
206
+ const hashed = MessageHash.keccak256(firstByteRemoved).bytes;
207
+ const lastTwentyBytes = hashed.slice(-20);
208
+ const accountAddress = '0x' + Buffer.from(lastTwentyBytes).toString('hex');
209
+ const publicKeyHex = rawPublicKey.pubKeyAsHex();
210
+ return {
211
+ accountAddress: getAddress(accountAddress),
212
+ publicKeyHex
213
+ };
214
+ }
215
+ async exportPrivateKey({ accountAddress, password = undefined, signedSessionId }) {
216
+ await this.verifyPassword({
217
+ accountAddress,
218
+ password,
219
+ walletOperation: WalletOperation.EXPORT_PRIVATE_KEY,
220
+ signedSessionId
221
+ });
222
+ const { derivedPrivateKey } = await this.exportKey({
223
+ accountAddress,
224
+ chainName: this.chainName,
225
+ password,
226
+ signedSessionId
227
+ });
228
+ return derivedPrivateKey;
229
+ }
230
+ async offlineExportPrivateKey({ keyShares, derivationPath }) {
231
+ const { derivedPrivateKey } = await this.offlineExportKey({
232
+ chainName: this.chainName,
233
+ keyShares,
234
+ derivationPath
235
+ });
236
+ return {
237
+ derivedPrivateKey
238
+ };
239
+ }
240
+ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
241
+ try {
242
+ let ceremonyCeremonyCompleteResolver;
243
+ const ceremonyCompletePromise = new Promise((resolve)=>{
244
+ ceremonyCeremonyCompleteResolver = resolve;
245
+ });
246
+ //remove 0x if it exists
247
+ const formattedPrivateKey = privateKey.startsWith('0x') ? privateKey.slice(2) : privateKey;
248
+ // TODO: validate private key for EVM
249
+ const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
250
+ chainName,
251
+ privateKey: formattedPrivateKey,
252
+ thresholdSignatureScheme,
253
+ onError: (error)=>{
254
+ this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
255
+ onError == null ? void 0 : onError(error);
256
+ },
257
+ onCeremonyComplete: (accountAddress, walletId)=>{
258
+ // update wallet map
259
+ const checksumAddress = getAddress(accountAddress);
260
+ this.walletMap[checksumAddress] = _extends({}, this.walletMap[checksumAddress] || {}, {
261
+ accountAddress: checksumAddress,
262
+ walletId,
263
+ chainName: this.chainName,
264
+ thresholdSignatureScheme,
265
+ clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
266
+ });
267
+ this.logger.debug('walletMap updated for wallet', {
268
+ context: {
269
+ accountAddress,
270
+ walletId,
271
+ walletMap: this.walletMap
272
+ }
273
+ });
274
+ ceremonyCeremonyCompleteResolver(undefined);
275
+ }
276
+ });
277
+ // Wait for the ceremony to complete before proceeding
278
+ await ceremonyCompletePromise;
279
+ if (!rawPublicKey || !clientKeyShares) {
280
+ throw new Error(ERROR_IMPORT_PRIVATE_KEY);
281
+ }
282
+ checkRawPublicKeyInstance(rawPublicKey);
283
+ const { accountAddress, publicKeyHex } = await this.deriveAccountAddress({
284
+ rawPublicKey: rawPublicKey
285
+ });
286
+ // Update client key shares in wallet map
287
+ await this.setClientKeySharesToLocalStorage({
288
+ accountAddress,
289
+ clientKeyShares,
290
+ overwriteOrMerge: 'overwrite'
291
+ });
292
+ await this.storeEncryptedBackupByWalletWithRetry({
293
+ accountAddress,
294
+ clientKeyShares,
295
+ password,
296
+ signedSessionId
297
+ });
298
+ return {
299
+ accountAddress,
300
+ rawPublicKey,
301
+ publicKeyHex
302
+ };
303
+ } catch (error) {
304
+ this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
305
+ throw error;
306
+ }
307
+ }
308
+ async getEvmWallets() {
309
+ const wallets = await this.getWallets();
310
+ const evmWallets = wallets.filter((wallet)=>wallet.chainName === 'eip155');
311
+ return evmWallets;
312
+ }
313
+ constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, baseClientRelayApiUrl }){
314
+ super({
315
+ environmentId,
316
+ authToken,
317
+ baseApiUrl,
318
+ baseMPCRelayApiUrl,
319
+ storageKey,
320
+ debug,
321
+ baseClientRelayApiUrl
322
+ }), this.chainName = 'EVM';
323
+ }
324
+ }
325
+
326
+ export { DynamicEvmWalletClient };
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@dynamic-labs-wallet/evm",
3
+ "version": "0.0.0-beta-191.1",
4
+ "license": "MIT",
5
+ "dependencies": {
6
+ "@dynamic-labs-wallet/browser": "0.0.0-beta-191.1"
7
+ },
8
+ "peerDependencies": {
9
+ "viem": "^2.22.1"
10
+ },
11
+ "nx": {
12
+ "sourceRoot": "packages/evm/src",
13
+ "projectType": "library",
14
+ "name": "evm",
15
+ "targets": {
16
+ "build": {}
17
+ }
18
+ },
19
+ "main": "./index.cjs.js",
20
+ "module": "./index.esm.js",
21
+ "types": "./index.esm.d.ts",
22
+ "exports": {
23
+ "./package.json": "./package.json",
24
+ ".": {
25
+ "types": "./index.esm.d.ts",
26
+ "import": "./index.esm.js",
27
+ "require": "./index.cjs.js",
28
+ "default": "./index.cjs.js"
29
+ }
30
+ }
31
+ }
@@ -0,0 +1,68 @@
1
+ import { DynamicWalletClient, EcdsaKeygenResult, EcdsaPublicKey, Ed25519KeygenResult, ThresholdSignatureScheme, DynamicWalletClientProps } from '@dynamic-labs-wallet/browser';
2
+ import { type PublicClient, type Chain, type SignableMessage, type TransactionSerializable } from 'viem';
3
+ export declare class DynamicEvmWalletClient extends DynamicWalletClient {
4
+ readonly chainName = "EVM";
5
+ constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, baseClientRelayApiUrl, }: DynamicWalletClientProps);
6
+ createViemPublicClient({ chain, rpcUrl, }: {
7
+ chain: Chain;
8
+ rpcUrl?: string;
9
+ }): PublicClient;
10
+ createWalletAccount({ thresholdSignatureScheme, password, onError, signedSessionId, }: {
11
+ thresholdSignatureScheme: ThresholdSignatureScheme;
12
+ password?: string;
13
+ onError?: (error: Error) => void;
14
+ signedSessionId?: string;
15
+ }): Promise<{
16
+ accountAddress: string;
17
+ publicKeyHex: string;
18
+ rawPublicKey: EcdsaPublicKey | Uint8Array | string | undefined;
19
+ }>;
20
+ signMessage({ message, accountAddress, password, signedSessionId, }: {
21
+ message: string;
22
+ accountAddress: string;
23
+ password?: string;
24
+ signedSessionId?: string;
25
+ }): Promise<`0x${string}`>;
26
+ verifyMessageSignature({ accountAddress, message, signature, }: {
27
+ accountAddress: string;
28
+ message: SignableMessage;
29
+ signature: any;
30
+ }): Promise<boolean>;
31
+ signTransaction({ senderAddress, transaction, password, signedSessionId, }: {
32
+ senderAddress: string;
33
+ transaction: TransactionSerializable;
34
+ password?: string;
35
+ signedSessionId?: string;
36
+ }): Promise<string>;
37
+ deriveAccountAddress({ rawPublicKey }: {
38
+ rawPublicKey: EcdsaPublicKey;
39
+ }): {
40
+ accountAddress: `0x${string}`;
41
+ publicKeyHex: any;
42
+ };
43
+ exportPrivateKey({ accountAddress, password, signedSessionId, }: {
44
+ accountAddress: string;
45
+ password?: string;
46
+ signedSessionId?: string;
47
+ }): Promise<string | undefined>;
48
+ offlineExportPrivateKey({ keyShares, derivationPath, }: {
49
+ keyShares: (EcdsaKeygenResult | Ed25519KeygenResult)[];
50
+ derivationPath?: string;
51
+ }): Promise<{
52
+ derivedPrivateKey: string | undefined;
53
+ }>;
54
+ importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, onError, signedSessionId, }: {
55
+ privateKey: string;
56
+ chainName: string;
57
+ thresholdSignatureScheme: ThresholdSignatureScheme;
58
+ password?: string;
59
+ onError?: (error: Error) => void;
60
+ signedSessionId?: string;
61
+ }): Promise<{
62
+ accountAddress: string;
63
+ publicKeyHex: string;
64
+ rawPublicKey: EcdsaPublicKey | Uint8Array | string | undefined;
65
+ }>;
66
+ getEvmWallets(): Promise<any>;
67
+ }
68
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const EVM_SIGN_MESSAGE_PREFIX = "\u0019Ethereum Signed Message:\n";
2
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/client/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,qCAAmC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const checkRawPublicKeyInstance: (rawPublicKey: any) => void;
2
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/client/helpers.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,iBAAkB,GAAG,SAI1D,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './client';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
package/src/index.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export * from './client';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
package/src/utils.d.ts ADDED
@@ -0,0 +1,6 @@
1
+ import type { EcdsaSignature } from '@dynamic-labs-wallet/browser';
2
+ export declare const formatEVMMessage: (message_: string | {
3
+ raw: string | Uint8Array;
4
+ }) => `0x${string}`;
5
+ export declare const serializeECDSASignature: (signature: EcdsaSignature) => `0x${string}`;
6
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../packages/src/utils.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAEnE,eAAO,MAAM,gBAAgB,aACjB,MAAM,GAAG;IAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAAA;CAAE,kBAUhD,CAAC;AAEF,eAAO,MAAM,uBAAuB,cAAe,cAAc,kBAMhE,CAAC"}