@dynamic-labs-wallet/browser 0.0.9 → 0.0.11
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 +1 -0
- package/index.cjs.js +803 -0
- package/index.esm.js +7 -3
- package/package.json +8 -7
- package/src/client.d.ts +3 -3
- package/src/client.d.ts.map +1 -1
package/index.cjs.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./src/index";
|
package/index.cjs.js
ADDED
|
@@ -0,0 +1,803 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@dynamic-labs-wallet/core');
|
|
4
|
+
var libMpcWeb = require('@dynamic-labs-wallet/lib-mpc-web');
|
|
5
|
+
|
|
6
|
+
const getMPCSignatureScheme = ({ signingAlgorithm, baseRelayUrl = core.MPC_RELAY_PROD_API_URL })=>{
|
|
7
|
+
switch(signingAlgorithm){
|
|
8
|
+
case core.SigningAlgorithm.ECDSA:
|
|
9
|
+
return new libMpcWeb.Ecdsa(baseRelayUrl);
|
|
10
|
+
case core.SigningAlgorithm.ED25519:
|
|
11
|
+
return new libMpcWeb.Ed25519(baseRelayUrl);
|
|
12
|
+
case core.SigningAlgorithm.BIP340:
|
|
13
|
+
return new libMpcWeb.BIP340(baseRelayUrl);
|
|
14
|
+
default:
|
|
15
|
+
throw new Error(`Unsupported signing algorithm: ${signingAlgorithm}`);
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const getMPCSigner = ({ chainName, baseRelayUrl })=>{
|
|
19
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
20
|
+
const signatureScheme = getMPCSignatureScheme({
|
|
21
|
+
signingAlgorithm: chainConfig.signingAlgorithm,
|
|
22
|
+
baseRelayUrl
|
|
23
|
+
});
|
|
24
|
+
return signatureScheme;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const bytesToBase64 = (arr)=>{
|
|
28
|
+
return btoa(Array.from(arr, (b)=>String.fromCharCode(b)).join(''));
|
|
29
|
+
};
|
|
30
|
+
const stringToBytes = (str)=>{
|
|
31
|
+
return new TextEncoder().encode(str);
|
|
32
|
+
};
|
|
33
|
+
const base64ToBytes = (base64)=>{
|
|
34
|
+
return new Uint8Array(Buffer.from(base64, 'base64'));
|
|
35
|
+
};
|
|
36
|
+
// Helper function to ensure proper base64 padding
|
|
37
|
+
const ensureBase64Padding = (str)=>{
|
|
38
|
+
return str.padEnd(Math.ceil(str.length / 4) * 4, '=');
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const getKey = async ({ password, salt })=>{
|
|
42
|
+
const passwordBytes = stringToBytes(password);
|
|
43
|
+
const initialKey = await crypto.subtle.importKey('raw', passwordBytes, {
|
|
44
|
+
name: 'PBKDF2'
|
|
45
|
+
}, false, [
|
|
46
|
+
'deriveKey'
|
|
47
|
+
]);
|
|
48
|
+
return crypto.subtle.deriveKey({
|
|
49
|
+
name: 'PBKDF2',
|
|
50
|
+
salt,
|
|
51
|
+
iterations: 100000,
|
|
52
|
+
hash: 'SHA-256'
|
|
53
|
+
}, initialKey, {
|
|
54
|
+
name: 'AES-GCM',
|
|
55
|
+
length: 256
|
|
56
|
+
}, false, [
|
|
57
|
+
'encrypt',
|
|
58
|
+
'decrypt'
|
|
59
|
+
]);
|
|
60
|
+
};
|
|
61
|
+
const encryptData = async ({ data, password })=>{
|
|
62
|
+
try {
|
|
63
|
+
// Generate a random salt and IV
|
|
64
|
+
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
65
|
+
const iv = crypto.getRandomValues(new Uint8Array(12)); // AES-GCM requires 12 bytes
|
|
66
|
+
const key = await getKey({
|
|
67
|
+
password,
|
|
68
|
+
salt
|
|
69
|
+
});
|
|
70
|
+
// Convert the input string to bytes
|
|
71
|
+
const dataBytes = new TextEncoder().encode(data);
|
|
72
|
+
// Encrypt the data
|
|
73
|
+
const encryptedData = await crypto.subtle.encrypt({
|
|
74
|
+
name: 'AES-GCM',
|
|
75
|
+
iv
|
|
76
|
+
}, key, dataBytes);
|
|
77
|
+
// Convert to base64 strings, ensure proper padding
|
|
78
|
+
return {
|
|
79
|
+
salt: bytesToBase64(salt),
|
|
80
|
+
iv: bytesToBase64(iv),
|
|
81
|
+
cipher: bytesToBase64(new Uint8Array(encryptedData))
|
|
82
|
+
};
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('Error encrypting data:', error);
|
|
85
|
+
throw new Error('Error encrypting data');
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
const decryptData = async ({ data, password })=>{
|
|
89
|
+
try {
|
|
90
|
+
const { salt, iv, cipher } = data;
|
|
91
|
+
// Ensure proper base64 padding for all values
|
|
92
|
+
const paddedSalt = ensureBase64Padding(salt);
|
|
93
|
+
const paddedIv = ensureBase64Padding(iv);
|
|
94
|
+
const paddedCipher = ensureBase64Padding(cipher);
|
|
95
|
+
const saltBytes = base64ToBytes(paddedSalt);
|
|
96
|
+
const ivBytes = base64ToBytes(paddedIv);
|
|
97
|
+
const cipherBytes = base64ToBytes(paddedCipher);
|
|
98
|
+
const key = await getKey({
|
|
99
|
+
password,
|
|
100
|
+
salt: saltBytes
|
|
101
|
+
});
|
|
102
|
+
const decryptedData = await crypto.subtle.decrypt({
|
|
103
|
+
name: 'AES-GCM',
|
|
104
|
+
iv: ivBytes
|
|
105
|
+
}, key, cipherBytes);
|
|
106
|
+
return new TextDecoder().decode(decryptedData);
|
|
107
|
+
} catch (error) {
|
|
108
|
+
console.error('Decryption error details:', error);
|
|
109
|
+
throw new Error(`Decryption failed`);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const GOOGLE_DRIVE_UPLOAD_API = 'https://www.googleapis.com';
|
|
114
|
+
const uploadFileToGoogleDrive = async ({ accessToken, fileName, jsonData })=>{
|
|
115
|
+
const metadata = {
|
|
116
|
+
name: fileName,
|
|
117
|
+
mimeType: 'application/json',
|
|
118
|
+
parents: [
|
|
119
|
+
'appDataFolder'
|
|
120
|
+
]
|
|
121
|
+
};
|
|
122
|
+
const form = new FormData();
|
|
123
|
+
form.append('metadata', new Blob([
|
|
124
|
+
JSON.stringify(metadata)
|
|
125
|
+
], {
|
|
126
|
+
type: 'application/json'
|
|
127
|
+
}));
|
|
128
|
+
form.append('file', new Blob([
|
|
129
|
+
JSON.stringify(jsonData)
|
|
130
|
+
], {
|
|
131
|
+
type: 'application/json'
|
|
132
|
+
}));
|
|
133
|
+
const response = await fetch(`${GOOGLE_DRIVE_UPLOAD_API}/upload/drive/v3/files?uploadType=multipart`, {
|
|
134
|
+
method: 'POST',
|
|
135
|
+
headers: {
|
|
136
|
+
Authorization: `Bearer ${accessToken}`
|
|
137
|
+
},
|
|
138
|
+
body: form
|
|
139
|
+
});
|
|
140
|
+
if (!response.ok) {
|
|
141
|
+
throw new Error('Error uploading file');
|
|
142
|
+
}
|
|
143
|
+
const result = await response.json();
|
|
144
|
+
return result; // Return file metadata, including file ID
|
|
145
|
+
};
|
|
146
|
+
const listFilesFromGoogleDrive = async ({ accessToken, name })=>{
|
|
147
|
+
// Step 1: List all files inside `appDataFolder` with the specified backup filename
|
|
148
|
+
const resp = await fetch(`${GOOGLE_DRIVE_UPLOAD_API}/drive/v3/files?q=${encodeURIComponent(`name='${name}'`)}&spaces=appDataFolder&orderBy=createdTime desc`, {
|
|
149
|
+
headers: {
|
|
150
|
+
Authorization: `Bearer ${accessToken}`
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
const data = await resp.json();
|
|
154
|
+
// If no files found, return null
|
|
155
|
+
if (!data.files || data.files.length === 0) {
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
const files = data.files;
|
|
159
|
+
return files;
|
|
160
|
+
};
|
|
161
|
+
const downloadFileFromGoogleDrive = async ({ accessToken, name })=>{
|
|
162
|
+
const files = await listFilesFromGoogleDrive({
|
|
163
|
+
accessToken,
|
|
164
|
+
name
|
|
165
|
+
});
|
|
166
|
+
// Get the most recent file
|
|
167
|
+
const fileMetadata = files[0];
|
|
168
|
+
// Fetch the file data using the file ID
|
|
169
|
+
const fileRes = await fetch(`${GOOGLE_DRIVE_UPLOAD_API}/drive/v3/files/${fileMetadata.id}?alt=media`, {
|
|
170
|
+
headers: {
|
|
171
|
+
Authorization: `Bearer ${accessToken}`
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
// Read the file's raw data
|
|
175
|
+
const fileRawData = await fileRes.text();
|
|
176
|
+
if (fileRawData.length === 0) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
return fileRawData;
|
|
180
|
+
};
|
|
181
|
+
|
|
182
|
+
const BACKUP_FILENAME = 'dynamicWalletSecretBackup.json';
|
|
183
|
+
|
|
184
|
+
class DynamicWalletClient {
|
|
185
|
+
async serverInitializeKeyGen({ chainName, clientPrimaryKeygenId, clientSecondaryKeygenId, thresholdSignatureScheme }) {
|
|
186
|
+
// Initilize keygen, create room, and create the wallet account on the server
|
|
187
|
+
const data = await this.apiClient.createWalletAccount({
|
|
188
|
+
chainName,
|
|
189
|
+
clientKeygenIds: [
|
|
190
|
+
clientPrimaryKeygenId,
|
|
191
|
+
clientSecondaryKeygenId
|
|
192
|
+
],
|
|
193
|
+
thresholdSignatureScheme
|
|
194
|
+
});
|
|
195
|
+
return data;
|
|
196
|
+
}
|
|
197
|
+
async clientInitializeKeyGen({ chainName }) {
|
|
198
|
+
// Get the mpc signer
|
|
199
|
+
const mpcSigner = getMPCSigner({
|
|
200
|
+
chainName,
|
|
201
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
202
|
+
});
|
|
203
|
+
// Initialize the keygen for the primary client and the secondary client shares
|
|
204
|
+
const keygenInitResults = await Promise.all([
|
|
205
|
+
mpcSigner.initKeygen(),
|
|
206
|
+
mpcSigner.initKeygen()
|
|
207
|
+
]);
|
|
208
|
+
const [clientPrimaryKeygenInitResult, clientSecondaryKeygenInitResult] = keygenInitResults;
|
|
209
|
+
return {
|
|
210
|
+
clientPrimaryKeygenInitResult,
|
|
211
|
+
clientSecondaryKeygenInitResult
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
async derivePublicKey({ chainName, keyShare }) {
|
|
215
|
+
const mpcSigner = getMPCSigner({
|
|
216
|
+
chainName,
|
|
217
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
218
|
+
});
|
|
219
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
220
|
+
let publicKey;
|
|
221
|
+
if (mpcSigner instanceof libMpcWeb.Ecdsa) {
|
|
222
|
+
publicKey = await mpcSigner.derivePubkey(keyShare, new Uint32Array(chainConfig.derivationPath));
|
|
223
|
+
} else if (mpcSigner instanceof libMpcWeb.Ed25519) {
|
|
224
|
+
publicKey = await mpcSigner.derivePubkey(keyShare, new Uint32Array(chainConfig.derivationPath));
|
|
225
|
+
}
|
|
226
|
+
return publicKey;
|
|
227
|
+
}
|
|
228
|
+
async clientKeyGen({ chainName, roomId, serverKeygenIds, clientPrimaryKeygenInitResult, clientSecondaryKeygenInitResult, thresholdSignatureScheme }) {
|
|
229
|
+
// Get the chain config and the mpc signer
|
|
230
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
231
|
+
const mpcSigner = getMPCSigner({
|
|
232
|
+
chainName,
|
|
233
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
234
|
+
});
|
|
235
|
+
// All parties receive the keygenIds from all OTHER parties
|
|
236
|
+
const clientPrimaryKeygenId = clientPrimaryKeygenInitResult.keygenId;
|
|
237
|
+
const clientSecondaryKeygenId = clientSecondaryKeygenInitResult.keygenId;
|
|
238
|
+
const clientPrimaryKeygenIds = [
|
|
239
|
+
...serverKeygenIds,
|
|
240
|
+
clientSecondaryKeygenId
|
|
241
|
+
];
|
|
242
|
+
const clientSecondaryKeygenIds = [
|
|
243
|
+
...serverKeygenIds,
|
|
244
|
+
clientPrimaryKeygenId
|
|
245
|
+
];
|
|
246
|
+
// Get the MPC config for the threshold signature scheme
|
|
247
|
+
const mpcConfig = core.MPC_CONFIG[thresholdSignatureScheme];
|
|
248
|
+
// All parties join the keygen room
|
|
249
|
+
const keygenResults = await Promise.all([
|
|
250
|
+
mpcSigner.keygen(roomId, mpcConfig.numberOfParties, mpcConfig.threshold, clientPrimaryKeygenInitResult, clientPrimaryKeygenIds),
|
|
251
|
+
mpcSigner.keygen(roomId, mpcConfig.numberOfParties, mpcConfig.threshold, clientSecondaryKeygenInitResult, clientSecondaryKeygenIds)
|
|
252
|
+
]);
|
|
253
|
+
const [clientPrimaryKeygenResult, clientSecondaryKeygenResult] = keygenResults;
|
|
254
|
+
// Pick the derivation path of the public key you want to sign for
|
|
255
|
+
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
256
|
+
// Get the public key for the derivation path
|
|
257
|
+
let rawPublicKey;
|
|
258
|
+
if (mpcSigner instanceof libMpcWeb.Ecdsa) {
|
|
259
|
+
rawPublicKey = await mpcSigner.derivePubkey(clientPrimaryKeygenResult, derivationPath);
|
|
260
|
+
} else if (mpcSigner instanceof libMpcWeb.Ed25519) {
|
|
261
|
+
rawPublicKey = await mpcSigner.derivePubkey(clientPrimaryKeygenResult, derivationPath);
|
|
262
|
+
} else if (mpcSigner instanceof libMpcWeb.BIP340) {
|
|
263
|
+
rawPublicKey = await mpcSigner.deriveTweakPubkey(clientPrimaryKeygenResult, derivationPath);
|
|
264
|
+
}
|
|
265
|
+
return {
|
|
266
|
+
rawPublicKey,
|
|
267
|
+
primaryKeygenResult: clientPrimaryKeygenResult,
|
|
268
|
+
secondaryKeygenResult: clientSecondaryKeygenResult
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
async keyGen({ chainName, thresholdSignatureScheme }) {
|
|
272
|
+
try {
|
|
273
|
+
const { clientPrimaryKeygenInitResult, clientSecondaryKeygenInitResult } = await this.clientInitializeKeyGen({
|
|
274
|
+
chainName
|
|
275
|
+
});
|
|
276
|
+
const data = await this.serverInitializeKeyGen({
|
|
277
|
+
chainName,
|
|
278
|
+
clientPrimaryKeygenId: clientPrimaryKeygenInitResult.keygenId,
|
|
279
|
+
clientSecondaryKeygenId: clientSecondaryKeygenInitResult.keygenId,
|
|
280
|
+
thresholdSignatureScheme
|
|
281
|
+
});
|
|
282
|
+
const { rawPublicKey, primaryKeygenResult, secondaryKeygenResult } = await this.clientKeyGen({
|
|
283
|
+
chainName,
|
|
284
|
+
roomId: data.roomId,
|
|
285
|
+
serverKeygenIds: data.serverKeygenIds,
|
|
286
|
+
clientPrimaryKeygenInitResult,
|
|
287
|
+
clientSecondaryKeygenInitResult,
|
|
288
|
+
thresholdSignatureScheme
|
|
289
|
+
});
|
|
290
|
+
return {
|
|
291
|
+
rawPublicKey,
|
|
292
|
+
primaryKeygenResult,
|
|
293
|
+
secondaryKeygenResult
|
|
294
|
+
};
|
|
295
|
+
} catch (error) {
|
|
296
|
+
console.error('Error creating wallet account', error);
|
|
297
|
+
throw new Error('Error creating wallet account');
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
async serverSign({ walletId, message }) {
|
|
301
|
+
// Create the room and sign the message
|
|
302
|
+
if (typeof message !== 'string') {
|
|
303
|
+
message = '0x' + Buffer.from(message).toString('hex');
|
|
304
|
+
}
|
|
305
|
+
const data = await this.apiClient.signMessage({
|
|
306
|
+
walletId,
|
|
307
|
+
message
|
|
308
|
+
});
|
|
309
|
+
return data;
|
|
310
|
+
}
|
|
311
|
+
async clientSign({ chainName, message, roomId, keyShare }) {
|
|
312
|
+
try {
|
|
313
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
314
|
+
const mpcSigner = getMPCSigner({
|
|
315
|
+
chainName,
|
|
316
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
317
|
+
});
|
|
318
|
+
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
319
|
+
let formattedMessage;
|
|
320
|
+
//note: Ecdsa can also be used by bitcoin, but only keccak256 is used by ethereum
|
|
321
|
+
if (mpcSigner instanceof libMpcWeb.Ecdsa) {
|
|
322
|
+
formattedMessage = libMpcWeb.MessageHash.keccak256(message);
|
|
323
|
+
} else if (mpcSigner instanceof libMpcWeb.Ed25519 && typeof message === 'string') {
|
|
324
|
+
formattedMessage = new TextEncoder().encode(message);
|
|
325
|
+
} else if (mpcSigner instanceof libMpcWeb.BIP340 && typeof message === 'string') {
|
|
326
|
+
formattedMessage = new TextEncoder().encode(message);
|
|
327
|
+
} else {
|
|
328
|
+
throw new Error('Unsupported signer type');
|
|
329
|
+
}
|
|
330
|
+
const signature = await mpcSigner.sign(roomId, keyShare, formattedMessage, derivationPath);
|
|
331
|
+
return signature;
|
|
332
|
+
} catch (error) {
|
|
333
|
+
console.error('Error in clientSign:', error);
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
async sign({ accountAddress, message, chainName }) {
|
|
338
|
+
const wallet = await this.getWallet({
|
|
339
|
+
accountAddress
|
|
340
|
+
});
|
|
341
|
+
// Perform the server sign
|
|
342
|
+
const data = await this.serverSign({
|
|
343
|
+
walletId: wallet.walletId,
|
|
344
|
+
message
|
|
345
|
+
});
|
|
346
|
+
// Perform the client sign and return the signature
|
|
347
|
+
const signature = await this.clientSign({
|
|
348
|
+
chainName,
|
|
349
|
+
message,
|
|
350
|
+
roomId: data.roomId,
|
|
351
|
+
keyShare: wallet.clientKeyShares[0]
|
|
352
|
+
});
|
|
353
|
+
return signature;
|
|
354
|
+
}
|
|
355
|
+
async refreshWalletAccountShares({ accountAddress }) {
|
|
356
|
+
const wallet = await this.getWallet({
|
|
357
|
+
accountAddress
|
|
358
|
+
});
|
|
359
|
+
const chainName = wallet.chainName;
|
|
360
|
+
const mpcSigner = getMPCSigner({
|
|
361
|
+
chainName,
|
|
362
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
363
|
+
});
|
|
364
|
+
// Create the room and refresh the shares
|
|
365
|
+
const data = await this.apiClient.refreshWalletAccountShares({
|
|
366
|
+
walletId: wallet.walletId
|
|
367
|
+
});
|
|
368
|
+
const roomId = data.roomId;
|
|
369
|
+
const keygenResults = await Promise.all([
|
|
370
|
+
mpcSigner.refresh(roomId, wallet.clientKeyShares[0]),
|
|
371
|
+
mpcSigner.refresh(roomId, wallet.clientKeyShares[1])
|
|
372
|
+
]);
|
|
373
|
+
return keygenResults;
|
|
374
|
+
}
|
|
375
|
+
async serverReshareRemainingParty({ walletId, clientKeygenIds }) {
|
|
376
|
+
const data = await this.apiClient.reshareRemainingParty({
|
|
377
|
+
walletId,
|
|
378
|
+
clientKeygenIds
|
|
379
|
+
});
|
|
380
|
+
return data;
|
|
381
|
+
}
|
|
382
|
+
async getExportId({ chainName, clientKeyShare }) {
|
|
383
|
+
const mpcSigner = getMPCSigner({
|
|
384
|
+
chainName,
|
|
385
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
386
|
+
});
|
|
387
|
+
const exportId = await mpcSigner.exportID(clientKeyShare);
|
|
388
|
+
return exportId;
|
|
389
|
+
}
|
|
390
|
+
async reshareRemainingParty({ accountAddress, thresholdSignatureScheme }) {
|
|
391
|
+
const wallet = await this.getWallet({
|
|
392
|
+
accountAddress
|
|
393
|
+
});
|
|
394
|
+
const chainName = wallet.chainName;
|
|
395
|
+
const mpcSigner = getMPCSigner({
|
|
396
|
+
chainName,
|
|
397
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
398
|
+
});
|
|
399
|
+
// Initialize the new party
|
|
400
|
+
const newPartyInitKeygen = await mpcSigner.initKeygen();
|
|
401
|
+
const newPartyInitKeygenId = newPartyInitKeygen.keygenId;
|
|
402
|
+
const clientKeygenId = await this.getExportId({
|
|
403
|
+
chainName,
|
|
404
|
+
clientKeyShare: wallet.clientKeyShares[0]
|
|
405
|
+
});
|
|
406
|
+
// Create the room and reshare the server share
|
|
407
|
+
const data = await this.serverReshareRemainingParty({
|
|
408
|
+
walletId: wallet.walletId,
|
|
409
|
+
clientKeygenIds: [
|
|
410
|
+
newPartyInitKeygenId,
|
|
411
|
+
clientKeygenId
|
|
412
|
+
]
|
|
413
|
+
});
|
|
414
|
+
const roomId = data.roomId;
|
|
415
|
+
// Get the MPC config for the threshold signature scheme
|
|
416
|
+
const mpcConfig = core.MPC_CONFIG[thresholdSignatureScheme];
|
|
417
|
+
const newClientPrimaryKeygenIds = [
|
|
418
|
+
data.serverKeygenId,
|
|
419
|
+
clientKeygenId
|
|
420
|
+
];
|
|
421
|
+
const clientSecondaryKeygenIds = [
|
|
422
|
+
data.serverKeygenId,
|
|
423
|
+
newPartyInitKeygenId
|
|
424
|
+
];
|
|
425
|
+
console.log('newClientPrimaryKeygenIds', newClientPrimaryKeygenIds);
|
|
426
|
+
console.log('clientSecondaryKeygenIds', clientSecondaryKeygenIds);
|
|
427
|
+
const keygenResults = await Promise.all([
|
|
428
|
+
mpcSigner.reshareNewParty(roomId, mpcConfig.threshold, mpcConfig.threshold, newPartyInitKeygen, newClientPrimaryKeygenIds),
|
|
429
|
+
mpcSigner.reshareRemainingParty(roomId, mpcConfig.threshold, wallet.clientKeyShares[1], clientSecondaryKeygenIds)
|
|
430
|
+
]);
|
|
431
|
+
return keygenResults;
|
|
432
|
+
}
|
|
433
|
+
async exportKey({ accountAddress, chainName }) {
|
|
434
|
+
const wallet = await this.getWallet({
|
|
435
|
+
accountAddress
|
|
436
|
+
});
|
|
437
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
438
|
+
const mpcSigner = getMPCSigner({
|
|
439
|
+
chainName,
|
|
440
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
441
|
+
});
|
|
442
|
+
const exportId = await this.getExportId({
|
|
443
|
+
chainName,
|
|
444
|
+
clientKeyShare: wallet.clientKeyShares[0]
|
|
445
|
+
});
|
|
446
|
+
const data = await this.apiClient.exportKey({
|
|
447
|
+
walletId: wallet.walletId,
|
|
448
|
+
exportId
|
|
449
|
+
});
|
|
450
|
+
const keyExportRaw = await mpcSigner.exportFullPrivateKey(data.roomId, wallet.clientKeyShares[0], exportId);
|
|
451
|
+
if (!keyExportRaw) {
|
|
452
|
+
throw new Error('Error exporting private key');
|
|
453
|
+
}
|
|
454
|
+
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
455
|
+
let derivedPrivateKey;
|
|
456
|
+
if (mpcSigner instanceof libMpcWeb.Ecdsa) {
|
|
457
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
458
|
+
} else if (mpcSigner instanceof libMpcWeb.Ed25519) {
|
|
459
|
+
derivedPrivateKey = keyExportRaw;
|
|
460
|
+
} else if (mpcSigner instanceof libMpcWeb.BIP340) {
|
|
461
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
462
|
+
}
|
|
463
|
+
return {
|
|
464
|
+
derivedPrivateKey
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
async offlineExportKey({ chainName, keyShares }) {
|
|
468
|
+
try {
|
|
469
|
+
if (!keyShares || keyShares.length !== 2) {
|
|
470
|
+
throw new Error('Must provide 2 key shares');
|
|
471
|
+
}
|
|
472
|
+
const mpcSigner = getMPCSigner({
|
|
473
|
+
chainName,
|
|
474
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
475
|
+
});
|
|
476
|
+
const walletKeyShares = keyShares.map((keyShare)=>{
|
|
477
|
+
return mpcSigner instanceof libMpcWeb.Ecdsa ? new libMpcWeb.EcdsaKeygenResult(keyShare.pubkey, keyShare.secretShare) : mpcSigner instanceof libMpcWeb.Ed25519 ? new libMpcWeb.Ed25519KeygenResult(keyShare.pubkey, keyShare.secretShare) : new libMpcWeb.BIP340KeygenResult(keyShare.pubkey, keyShare.secretShare);
|
|
478
|
+
});
|
|
479
|
+
const keyExportRaw = await mpcSigner.offlineExportFullPrivateKey(walletKeyShares);
|
|
480
|
+
if (!keyExportRaw) {
|
|
481
|
+
throw new Error('Error exporting private key: Export returned null');
|
|
482
|
+
}
|
|
483
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
484
|
+
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
485
|
+
let derivedPrivateKey;
|
|
486
|
+
if (mpcSigner instanceof libMpcWeb.Ecdsa) {
|
|
487
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
488
|
+
} else if (mpcSigner instanceof libMpcWeb.Ed25519) {
|
|
489
|
+
derivedPrivateKey = keyExportRaw;
|
|
490
|
+
} else if (mpcSigner instanceof libMpcWeb.BIP340) {
|
|
491
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
492
|
+
}
|
|
493
|
+
return {
|
|
494
|
+
derivedPrivateKey
|
|
495
|
+
};
|
|
496
|
+
} catch (error) {
|
|
497
|
+
console.error('Error in offlineExportKey:', error);
|
|
498
|
+
throw error;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
async encryptKeyShare({ keyShare, password }) {
|
|
502
|
+
const serializedKeyShare = JSON.stringify(keyShare);
|
|
503
|
+
const encryptedKeyShare = await encryptData({
|
|
504
|
+
data: serializedKeyShare,
|
|
505
|
+
password: password != null ? password : this.environmentId
|
|
506
|
+
});
|
|
507
|
+
// stringify the encrypted key share, convert to base64, and store it
|
|
508
|
+
const serializedEncryptedKeyShare = Buffer.from(JSON.stringify(encryptedKeyShare)).toString('base64');
|
|
509
|
+
return serializedEncryptedKeyShare;
|
|
510
|
+
}
|
|
511
|
+
async storeEncryptedBackupByWallet({ accountAddress, password }) {
|
|
512
|
+
await this.getWallet({
|
|
513
|
+
accountAddress
|
|
514
|
+
});
|
|
515
|
+
const encryptedKeyShares = await Promise.all(this.walletMap[accountAddress].clientKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
516
|
+
keyShare,
|
|
517
|
+
password
|
|
518
|
+
})));
|
|
519
|
+
const data = await this.apiClient.storeEncryptedBackupByWallet({
|
|
520
|
+
walletId: this.walletMap[accountAddress].walletId,
|
|
521
|
+
encryptedKeyShares,
|
|
522
|
+
passwordEncrypted: password ? true : false
|
|
523
|
+
});
|
|
524
|
+
return data;
|
|
525
|
+
}
|
|
526
|
+
async decryptKeyShare({ keyShare, password }) {
|
|
527
|
+
const decodedKeyShare = JSON.parse(Buffer.from(keyShare, 'base64').toString());
|
|
528
|
+
const decryptedKeyShare = await decryptData({
|
|
529
|
+
data: decodedKeyShare,
|
|
530
|
+
password: password != null ? password : this.environmentId
|
|
531
|
+
});
|
|
532
|
+
const deserializedKeyShare = JSON.parse(decryptedKeyShare);
|
|
533
|
+
return deserializedKeyShare;
|
|
534
|
+
}
|
|
535
|
+
async recoverEncryptedBackupByWallet({ accountAddress, password, keyShareIds }) {
|
|
536
|
+
const data = await this.apiClient.recoverEncryptedBackupByWallet({
|
|
537
|
+
walletId: this.walletMap[accountAddress].walletId,
|
|
538
|
+
keyShareIds
|
|
539
|
+
});
|
|
540
|
+
const decryptedKeyShares = await Promise.all(data.keyShares.map((keyShare)=>this.decryptKeyShare({
|
|
541
|
+
keyShare: keyShare.encryptedAccountCredential,
|
|
542
|
+
password: password != null ? password : this.environmentId
|
|
543
|
+
})));
|
|
544
|
+
decryptedKeyShares.forEach((keyShare)=>{
|
|
545
|
+
this.restoreBackupShare({
|
|
546
|
+
walletId: this.walletMap[accountAddress].walletId,
|
|
547
|
+
accountAddress,
|
|
548
|
+
chainName: data.chainName,
|
|
549
|
+
keyShare,
|
|
550
|
+
thresholdSignatureScheme: data.thresholdSignatureScheme
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
return decryptedKeyShares;
|
|
554
|
+
}
|
|
555
|
+
restoreBackupShare({ walletId, accountAddress, chainName, keyShare, thresholdSignatureScheme }) {
|
|
556
|
+
var _this_walletMap_accountAddress;
|
|
557
|
+
this.walletMap[accountAddress] = {
|
|
558
|
+
walletId,
|
|
559
|
+
chainName,
|
|
560
|
+
accountAddress,
|
|
561
|
+
clientKeyShares: [
|
|
562
|
+
...((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? undefined : _this_walletMap_accountAddress.clientKeyShares) || [],
|
|
563
|
+
keyShare
|
|
564
|
+
],
|
|
565
|
+
thresholdSignatureScheme
|
|
566
|
+
};
|
|
567
|
+
}
|
|
568
|
+
async backupFileToGoogleDrive({ oauthAccountId, fileName = BACKUP_FILENAME, jsonData, password }) {
|
|
569
|
+
const encryptedKeyShare = await this.encryptKeyShare({
|
|
570
|
+
keyShare: jsonData,
|
|
571
|
+
password
|
|
572
|
+
});
|
|
573
|
+
const accessToken = await this.apiClient.getAccessToken({
|
|
574
|
+
oauthAccountId
|
|
575
|
+
});
|
|
576
|
+
const uploadMetadata = await uploadFileToGoogleDrive({
|
|
577
|
+
accessToken,
|
|
578
|
+
fileName,
|
|
579
|
+
jsonData: encryptedKeyShare
|
|
580
|
+
});
|
|
581
|
+
return uploadMetadata;
|
|
582
|
+
}
|
|
583
|
+
async getBackupFileFromGoogleDrive({ oauthAccountId, name = BACKUP_FILENAME, password }) {
|
|
584
|
+
const accessToken = await this.apiClient.getAccessToken({
|
|
585
|
+
oauthAccountId
|
|
586
|
+
});
|
|
587
|
+
const file = await downloadFileFromGoogleDrive({
|
|
588
|
+
accessToken,
|
|
589
|
+
name
|
|
590
|
+
});
|
|
591
|
+
if (!file) {
|
|
592
|
+
return null;
|
|
593
|
+
}
|
|
594
|
+
const decryptedKeyShare = await this.decryptKeyShare({
|
|
595
|
+
keyShare: file,
|
|
596
|
+
password: password != null ? password : this.environmentId
|
|
597
|
+
});
|
|
598
|
+
return decryptedKeyShare;
|
|
599
|
+
}
|
|
600
|
+
async importRawPrivateKey({ chainName, privateKey, thresholdSignatureScheme }) {
|
|
601
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
602
|
+
const mpcSigner = getMPCSigner({
|
|
603
|
+
chainName,
|
|
604
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
605
|
+
});
|
|
606
|
+
// 1. 2 parties on the client side create keygenInit
|
|
607
|
+
const { clientPrimaryKeygenInitResult, clientSecondaryKeygenInitResult } = await this.clientInitializeKeyGen({
|
|
608
|
+
chainName
|
|
609
|
+
});
|
|
610
|
+
const clientSecondaryKeygenId = clientSecondaryKeygenInitResult.keygenId;
|
|
611
|
+
const clientPrimaryKeygenId = clientPrimaryKeygenInitResult.keygenId;
|
|
612
|
+
// 2. server to create a room for importing the private key
|
|
613
|
+
// server will do 3 things:
|
|
614
|
+
// --- 1. init keygen for the server as a party
|
|
615
|
+
// --- 2. open a room and return the roomId for the ceremony
|
|
616
|
+
// --- 3. join the room as a party for the 2/3 ceremony
|
|
617
|
+
const { roomId, serverKeygenIds } = await this.apiClient.importPrivateKey({
|
|
618
|
+
chainName,
|
|
619
|
+
clientKeygenIds: [
|
|
620
|
+
clientPrimaryKeygenId,
|
|
621
|
+
clientSecondaryKeygenId
|
|
622
|
+
],
|
|
623
|
+
thresholdSignatureScheme
|
|
624
|
+
});
|
|
625
|
+
const { threshold } = core.getTSSConfig(thresholdSignatureScheme);
|
|
626
|
+
// prep
|
|
627
|
+
const importerKeygenIds = [
|
|
628
|
+
...serverKeygenIds,
|
|
629
|
+
clientSecondaryKeygenId
|
|
630
|
+
];
|
|
631
|
+
const recipientKeygenIds = [
|
|
632
|
+
...serverKeygenIds,
|
|
633
|
+
clientPrimaryKeygenId
|
|
634
|
+
];
|
|
635
|
+
// 3. Join the keygen room for the ceremony
|
|
636
|
+
const [clientPrimaryKeygenResult, clientSecondaryKeygenResult] = await Promise.all([
|
|
637
|
+
mpcSigner.importPrivateKeyImporter(roomId, threshold, privateKey, clientPrimaryKeygenInitResult, importerKeygenIds),
|
|
638
|
+
mpcSigner.importPrivateKeyRecipient(roomId, threshold, clientSecondaryKeygenInitResult, recipientKeygenIds)
|
|
639
|
+
]);
|
|
640
|
+
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
641
|
+
// Get the public key for the derivation path
|
|
642
|
+
let rawPublicKey;
|
|
643
|
+
if (mpcSigner instanceof libMpcWeb.Ecdsa) {
|
|
644
|
+
rawPublicKey = await mpcSigner.derivePubkey(clientPrimaryKeygenResult, derivationPath);
|
|
645
|
+
} else if (mpcSigner instanceof libMpcWeb.Ed25519) {
|
|
646
|
+
rawPublicKey = await mpcSigner.derivePubkey(clientPrimaryKeygenResult, derivationPath);
|
|
647
|
+
} else if (mpcSigner instanceof libMpcWeb.BIP340) {
|
|
648
|
+
rawPublicKey = await mpcSigner.deriveTweakPubkey(clientPrimaryKeygenResult, derivationPath);
|
|
649
|
+
}
|
|
650
|
+
return {
|
|
651
|
+
rawPublicKey,
|
|
652
|
+
primaryKeygenResult: clientPrimaryKeygenResult,
|
|
653
|
+
secondaryKeygenResult: clientSecondaryKeygenResult
|
|
654
|
+
};
|
|
655
|
+
}
|
|
656
|
+
async exportClientKeyshares({ accountAddress }) {
|
|
657
|
+
const clientKeyshares = await this.getClientKeyshares({
|
|
658
|
+
accountAddress
|
|
659
|
+
});
|
|
660
|
+
const text = JSON.stringify(clientKeyshares);
|
|
661
|
+
const blob = new Blob([
|
|
662
|
+
text
|
|
663
|
+
], {
|
|
664
|
+
type: 'text/plain'
|
|
665
|
+
});
|
|
666
|
+
const url = URL.createObjectURL(blob);
|
|
667
|
+
const a = document.createElement('a');
|
|
668
|
+
a.href = url;
|
|
669
|
+
a.download = 'clientKeyshare.txt';
|
|
670
|
+
a.click();
|
|
671
|
+
}
|
|
672
|
+
async getClientKeyshares({ accountAddress }) {
|
|
673
|
+
const wallet = await this.getWallet({
|
|
674
|
+
accountAddress
|
|
675
|
+
});
|
|
676
|
+
return wallet.clientKeyShares;
|
|
677
|
+
}
|
|
678
|
+
async getWallet({ accountAddress }) {
|
|
679
|
+
if (accountAddress) {
|
|
680
|
+
if (this.walletMap[accountAddress] && this.walletMap[accountAddress].clientKeyShares.length > 0) {
|
|
681
|
+
return this.walletMap[accountAddress];
|
|
682
|
+
} else {
|
|
683
|
+
var _user_verifiedCredentials;
|
|
684
|
+
const user = await this.apiClient.getUser();
|
|
685
|
+
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? undefined : _user_verifiedCredentials.find((vc)=>vc.address === accountAddress);
|
|
686
|
+
console.log('need to restore wallet', wallet);
|
|
687
|
+
const clientShares = wallet.walletProperties.keyShares.filter((ks)=>ks.backupLocation === 'dynamic');
|
|
688
|
+
console.log('clientShares', clientShares);
|
|
689
|
+
// restore backup
|
|
690
|
+
const decryptedKeyShares = await this.recoverEncryptedBackupByWallet({
|
|
691
|
+
accountAddress,
|
|
692
|
+
password: this.environmentId
|
|
693
|
+
});
|
|
694
|
+
//todo: check to see if their are other backups ie google drive, etc
|
|
695
|
+
console.log('recovery decryptedKeyShares', decryptedKeyShares);
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
const walletCount = Object.keys(this.walletMap).length;
|
|
699
|
+
// if there are no wallets, throw an error
|
|
700
|
+
if (walletCount === 0) {
|
|
701
|
+
throw new Error('No wallets found');
|
|
702
|
+
}
|
|
703
|
+
// if there is only one wallet, return it by default
|
|
704
|
+
if (walletCount === 1) {
|
|
705
|
+
return Object.values(this.walletMap)[0];
|
|
706
|
+
}
|
|
707
|
+
if (!accountAddress) {
|
|
708
|
+
throw new Error('Must provide an account address');
|
|
709
|
+
}
|
|
710
|
+
return this.walletMap[accountAddress];
|
|
711
|
+
}
|
|
712
|
+
async getWallets() {
|
|
713
|
+
var _user_verifiedCredentials;
|
|
714
|
+
const user = await this.apiClient.getUser();
|
|
715
|
+
const waasWallets = (_user_verifiedCredentials = user.verifiedCredentials) == null ? undefined : _user_verifiedCredentials.filter((vc)=>vc.walletName === 'dynamicwaas');
|
|
716
|
+
const wallets = waasWallets.map((vc)=>({
|
|
717
|
+
walletId: vc.id,
|
|
718
|
+
chainName: vc.chain,
|
|
719
|
+
accountAddress: vc.address
|
|
720
|
+
}));
|
|
721
|
+
this.walletMap = wallets.reduce((acc, wallet)=>{
|
|
722
|
+
acc[wallet.accountAddress] = {
|
|
723
|
+
walletId: wallet.walletId,
|
|
724
|
+
chainName: wallet.chainName,
|
|
725
|
+
accountAddress: wallet.accountAddress,
|
|
726
|
+
clientKeyShares: [],
|
|
727
|
+
thresholdSignatureScheme: undefined
|
|
728
|
+
};
|
|
729
|
+
return acc;
|
|
730
|
+
}, {});
|
|
731
|
+
return wallets;
|
|
732
|
+
}
|
|
733
|
+
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl }){
|
|
734
|
+
this.walletMap = {} // todo: store in session storage
|
|
735
|
+
;
|
|
736
|
+
this.environmentId = environmentId;
|
|
737
|
+
this.baseMPCRelayApiUrl = baseMPCRelayApiUrl;
|
|
738
|
+
this.apiClient = new core.DynamicApiClient({
|
|
739
|
+
environmentId,
|
|
740
|
+
authToken,
|
|
741
|
+
baseApiUrl
|
|
742
|
+
});
|
|
743
|
+
this.getWallets();
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
Object.defineProperty(exports, "BIP340", {
|
|
748
|
+
enumerable: true,
|
|
749
|
+
get: function () { return libMpcWeb.BIP340; }
|
|
750
|
+
});
|
|
751
|
+
Object.defineProperty(exports, "BIP340InitKeygenResult", {
|
|
752
|
+
enumerable: true,
|
|
753
|
+
get: function () { return libMpcWeb.BIP340InitKeygenResult; }
|
|
754
|
+
});
|
|
755
|
+
Object.defineProperty(exports, "BIP340KeygenResult", {
|
|
756
|
+
enumerable: true,
|
|
757
|
+
get: function () { return libMpcWeb.BIP340KeygenResult; }
|
|
758
|
+
});
|
|
759
|
+
Object.defineProperty(exports, "Ecdsa", {
|
|
760
|
+
enumerable: true,
|
|
761
|
+
get: function () { return libMpcWeb.Ecdsa; }
|
|
762
|
+
});
|
|
763
|
+
Object.defineProperty(exports, "EcdsaInitKeygenResult", {
|
|
764
|
+
enumerable: true,
|
|
765
|
+
get: function () { return libMpcWeb.EcdsaInitKeygenResult; }
|
|
766
|
+
});
|
|
767
|
+
Object.defineProperty(exports, "EcdsaKeygenResult", {
|
|
768
|
+
enumerable: true,
|
|
769
|
+
get: function () { return libMpcWeb.EcdsaKeygenResult; }
|
|
770
|
+
});
|
|
771
|
+
Object.defineProperty(exports, "EcdsaPublicKey", {
|
|
772
|
+
enumerable: true,
|
|
773
|
+
get: function () { return libMpcWeb.EcdsaPublicKey; }
|
|
774
|
+
});
|
|
775
|
+
Object.defineProperty(exports, "EcdsaSignature", {
|
|
776
|
+
enumerable: true,
|
|
777
|
+
get: function () { return libMpcWeb.EcdsaSignature; }
|
|
778
|
+
});
|
|
779
|
+
Object.defineProperty(exports, "Ed25519", {
|
|
780
|
+
enumerable: true,
|
|
781
|
+
get: function () { return libMpcWeb.Ed25519; }
|
|
782
|
+
});
|
|
783
|
+
Object.defineProperty(exports, "Ed25519InitKeygenResult", {
|
|
784
|
+
enumerable: true,
|
|
785
|
+
get: function () { return libMpcWeb.Ed25519InitKeygenResult; }
|
|
786
|
+
});
|
|
787
|
+
Object.defineProperty(exports, "Ed25519KeygenResult", {
|
|
788
|
+
enumerable: true,
|
|
789
|
+
get: function () { return libMpcWeb.Ed25519KeygenResult; }
|
|
790
|
+
});
|
|
791
|
+
Object.defineProperty(exports, "MessageHash", {
|
|
792
|
+
enumerable: true,
|
|
793
|
+
get: function () { return libMpcWeb.MessageHash; }
|
|
794
|
+
});
|
|
795
|
+
exports.DynamicWalletClient = DynamicWalletClient;
|
|
796
|
+
exports.getMPCSignatureScheme = getMPCSignatureScheme;
|
|
797
|
+
exports.getMPCSigner = getMPCSigner;
|
|
798
|
+
Object.keys(core).forEach(function (k) {
|
|
799
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
800
|
+
enumerable: true,
|
|
801
|
+
get: function () { return core[k]; }
|
|
802
|
+
});
|
|
803
|
+
});
|
package/index.esm.js
CHANGED
|
@@ -299,6 +299,9 @@ class DynamicWalletClient {
|
|
|
299
299
|
}
|
|
300
300
|
async serverSign({ walletId, message }) {
|
|
301
301
|
// Create the room and sign the message
|
|
302
|
+
if (typeof message !== 'string') {
|
|
303
|
+
message = '0x' + Buffer.from(message).toString('hex');
|
|
304
|
+
}
|
|
302
305
|
const data = await this.apiClient.signMessage({
|
|
303
306
|
walletId,
|
|
304
307
|
message
|
|
@@ -314,11 +317,12 @@ class DynamicWalletClient {
|
|
|
314
317
|
});
|
|
315
318
|
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
316
319
|
let formattedMessage;
|
|
320
|
+
//note: Ecdsa can also be used by bitcoin, but only keccak256 is used by ethereum
|
|
317
321
|
if (mpcSigner instanceof Ecdsa) {
|
|
318
|
-
formattedMessage = MessageHash.
|
|
319
|
-
} else if (mpcSigner instanceof Ed25519) {
|
|
322
|
+
formattedMessage = MessageHash.keccak256(message);
|
|
323
|
+
} else if (mpcSigner instanceof Ed25519 && typeof message === 'string') {
|
|
320
324
|
formattedMessage = new TextEncoder().encode(message);
|
|
321
|
-
} else if (mpcSigner instanceof BIP340) {
|
|
325
|
+
} else if (mpcSigner instanceof BIP340 && typeof message === 'string') {
|
|
322
326
|
formattedMessage = new TextEncoder().encode(message);
|
|
323
327
|
} else {
|
|
324
328
|
throw new Error('Unsupported signer type');
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/browser",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.11",
|
|
4
4
|
"dependencies": {
|
|
5
|
-
"@dynamic-labs-wallet/core": "0.0.
|
|
6
|
-
"@dynamic-labs-wallet/lib-mpc-web": "0.0.
|
|
5
|
+
"@dynamic-labs-wallet/core": "0.0.11",
|
|
6
|
+
"@dynamic-labs-wallet/lib-mpc-web": "0.0.11"
|
|
7
7
|
},
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"access": "restricted"
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"projectType": "library",
|
|
14
14
|
"name": "browser"
|
|
15
15
|
},
|
|
16
|
-
"
|
|
16
|
+
"type": "module",
|
|
17
|
+
"main": "./index.cjs.js",
|
|
17
18
|
"module": "./index.esm.js",
|
|
18
19
|
"types": "./index.esm.d.ts",
|
|
19
20
|
"exports": {
|
|
@@ -21,8 +22,8 @@
|
|
|
21
22
|
".": {
|
|
22
23
|
"types": "./index.esm.d.ts",
|
|
23
24
|
"import": "./index.esm.js",
|
|
24
|
-
"
|
|
25
|
+
"require": "./index.cjs.js",
|
|
26
|
+
"default": "./index.cjs.js"
|
|
25
27
|
}
|
|
26
|
-
}
|
|
27
|
-
"type": "module"
|
|
28
|
+
}
|
|
28
29
|
}
|
package/src/client.d.ts
CHANGED
|
@@ -57,17 +57,17 @@ export declare class DynamicWalletClient {
|
|
|
57
57
|
}>;
|
|
58
58
|
serverSign({ walletId, message, }: {
|
|
59
59
|
walletId: string;
|
|
60
|
-
message: string;
|
|
60
|
+
message: string | Uint8Array;
|
|
61
61
|
}): Promise<any>;
|
|
62
62
|
clientSign({ chainName, message, roomId, keyShare, }: {
|
|
63
63
|
chainName: string;
|
|
64
|
-
message: string;
|
|
64
|
+
message: string | Uint8Array;
|
|
65
65
|
roomId: string;
|
|
66
66
|
keyShare: ClientKeyShare;
|
|
67
67
|
}): Promise<Uint8Array | EcdsaSignature>;
|
|
68
68
|
sign({ accountAddress, message, chainName, }: {
|
|
69
69
|
accountAddress?: string;
|
|
70
|
-
message: string;
|
|
70
|
+
message: string | Uint8Array;
|
|
71
71
|
chainName: string;
|
|
72
72
|
}): Promise<Uint8Array | EcdsaSignature>;
|
|
73
73
|
refreshWalletAccountShares({ accountAddress, }: {
|
package/src/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../packages/src/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,wBAAwB,EACxB,gBAAgB,EAEjB,MAAM,2BAA2B,CAAC;AAEnC,OAAO,EAIL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAElB,cAAc,EACf,MAAM,kCAAkC,CAAC;AAE1C,OAAO,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAOrE,UAAU,gBAAgB;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,cAAc,EAAE,CAAC;IAClC,wBAAwB,CAAC,EAAE,wBAAwB,CAAC;CACrD;AAED,qBAAa,mBAAmB;IACvB,aAAa,EAAE,MAAM,CAAC;IAE7B,SAAS,CAAC,SAAS,EAAE,gBAAgB,CAAC;IACtC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAM;IAC3D,SAAS,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;gBAE1B,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACV,kBAAkB,GACnB,EAAE;QACD,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B;IAWK,sBAAsB,CAAC,EAC3B,SAAS,EACT,qBAAqB,EACrB,uBAAuB,EACvB,wBAAwB,GACzB,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,qBAAqB,EAAE,MAAM,CAAC;QAC9B,uBAAuB,EAAE,MAAM,CAAC;QAChC,wBAAwB,EAAE,wBAAwB,CAAC;KACpD;IAWK,sBAAsB,CAAC,EAAE,SAAS,EAAE,EAAE;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE;;;;IAqB3D,eAAe,CAAC,EACpB,SAAS,EACT,QAAQ,GACT,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,cAAc,CAAC;KAC1B;IAqBK,YAAY,CAAC,EACjB,SAAS,EACT,MAAM,EACN,eAAe,EACf,6BAA6B,EAC7B,+BAA+B,EAC/B,wBAAwB,GACzB,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,eAAe,EAAE,MAAM,EAAE,CAAC;QAC1B,6BAA6B,EAAE,sBAAsB,CAAC;QACtD,+BAA+B,EAAE,sBAAsB,CAAC;QACxD,wBAAwB,EAAE,wBAAwB,CAAC;KACpD;;;;;IAwEK,MAAM,CAAC,EACX,SAAS,EACT,wBAAwB,GACzB,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,wBAAwB,EAAE,wBAAwB,CAAC;KACpD;;;;;IAiCK,UAAU,CAAC,EACf,QAAQ,EACR,OAAO,GACR,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../packages/src/client.ts"],"names":[],"mappings":"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"}
|