@dynamic-labs-wallet/node 0.0.0-beta.146.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 +1 -0
- package/index.cjs.js +1151 -0
- package/index.esm.d.ts +1 -0
- package/index.esm.js +1087 -0
- package/internal/core/bip340.d.ts +22 -0
- package/internal/core/bip340.js +1 -0
- package/internal/core/common.d.ts +1 -0
- package/internal/core/common.js +1 -0
- package/internal/core/ecdsa.d.ts +23 -0
- package/internal/core/ecdsa.js +1 -0
- package/internal/core/ed25519.d.ts +22 -0
- package/internal/core/ed25519.js +1 -0
- package/internal/core/index.d.ts +6 -0
- package/internal/core/index.js +1 -0
- package/internal/core/native.d.ts +103 -0
- package/internal/core/native.js +1 -0
- package/internal/core/types.d.ts +58 -0
- package/internal/core/types.js +1 -0
- package/internal/node/index.d.ts +11 -0
- package/internal/node/index.js +1 -0
- package/internal/node/native/libmpc_executor_linux_arm64_nodejs.node +0 -0
- package/internal/node/native/libmpc_executor_linux_x86_64_nodejs.node +0 -0
- package/internal/node/native/libmpc_executor_macos_arm64_nodejs.node +0 -0
- package/internal/node/native/libmpc_executor_macos_x86_64_nodejs.node +0 -0
- package/internal/node/native.d.ts +2 -0
- package/internal/node/native.js +1 -0
- package/package.json +34 -0
- package/src/backup/encryption.d.ts +22 -0
- package/src/backup/encryption.d.ts.map +1 -0
- package/src/client.d.ts +249 -0
- package/src/client.d.ts.map +1 -0
- package/src/constants.d.ts +2 -0
- package/src/constants.d.ts.map +1 -0
- package/src/index.d.ts +6 -0
- package/src/index.d.ts.map +1 -0
- package/src/mpc/index.d.ts +3 -0
- package/src/mpc/index.d.ts.map +1 -0
- package/src/mpc/mpc.d.ts +12 -0
- package/src/mpc/mpc.d.ts.map +1 -0
- package/src/mpc/types.d.ts +6 -0
- package/src/mpc/types.d.ts.map +1 -0
- package/src/services/logger.d.ts +3 -0
- package/src/services/logger.d.ts.map +1 -0
- package/src/types.d.ts +12 -0
- package/src/types.d.ts.map +1 -0
- package/src/utils.d.ts +34 -0
- package/src/utils.d.ts.map +1 -0
package/index.cjs.js
ADDED
|
@@ -0,0 +1,1151 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@dynamic-labs-wallet/core');
|
|
4
|
+
var node = require('./internal/node');
|
|
5
|
+
var logger$1 = require('@dynamic-labs/logger');
|
|
6
|
+
var crypto = require('crypto');
|
|
7
|
+
|
|
8
|
+
const getMPCSignatureScheme = ({ signingAlgorithm, baseRelayUrl = core.MPC_RELAY_PROD_API_URL })=>{
|
|
9
|
+
switch(signingAlgorithm){
|
|
10
|
+
case core.SigningAlgorithm.ECDSA:
|
|
11
|
+
return new node.Ecdsa(baseRelayUrl);
|
|
12
|
+
case core.SigningAlgorithm.ED25519:
|
|
13
|
+
return new node.Ed25519(baseRelayUrl);
|
|
14
|
+
case core.SigningAlgorithm.BIP340:
|
|
15
|
+
return new node.BIP340(baseRelayUrl);
|
|
16
|
+
default:
|
|
17
|
+
throw new Error(`Unsupported signing algorithm: ${signingAlgorithm}`);
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const getMPCSigner = ({ chainName, baseRelayUrl })=>{
|
|
21
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
22
|
+
const signatureScheme = getMPCSignatureScheme({
|
|
23
|
+
signingAlgorithm: chainConfig.signingAlgorithm,
|
|
24
|
+
baseRelayUrl
|
|
25
|
+
});
|
|
26
|
+
return signatureScheme;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function _extends() {
|
|
30
|
+
_extends = Object.assign || function assign(target) {
|
|
31
|
+
for(var i = 1; i < arguments.length; i++){
|
|
32
|
+
var source = arguments[i];
|
|
33
|
+
for(var key in source)if (Object.prototype.hasOwnProperty.call(source, key)) target[key] = source[key];
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
};
|
|
37
|
+
return _extends.apply(this, arguments);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const logger = new logger$1.Logger('DynamicWaasWalletClient');
|
|
41
|
+
|
|
42
|
+
const bytesToBase64 = (arr)=>{
|
|
43
|
+
return btoa(Array.from(arr, (b)=>String.fromCharCode(b)).join(''));
|
|
44
|
+
};
|
|
45
|
+
const stringToBytes = (str)=>{
|
|
46
|
+
return new TextEncoder().encode(str);
|
|
47
|
+
};
|
|
48
|
+
const base64ToBytes = (base64)=>{
|
|
49
|
+
return new Uint8Array(Buffer.from(base64, 'base64'));
|
|
50
|
+
};
|
|
51
|
+
// Helper function to ensure proper base64 padding
|
|
52
|
+
const ensureBase64Padding = (str)=>{
|
|
53
|
+
return str.padEnd(Math.ceil(str.length / 4) * 4, '=');
|
|
54
|
+
};
|
|
55
|
+
const isHexString = (str)=>{
|
|
56
|
+
// Remove 0x prefix if present
|
|
57
|
+
const hex = str.startsWith('0x') ? str.slice(2) : str;
|
|
58
|
+
// Check if string contains only hex characters
|
|
59
|
+
return /^[0-9A-Fa-f]+$/.test(hex);
|
|
60
|
+
};
|
|
61
|
+
const getExternalServerKeyShareBackupInfo = (params)=>{
|
|
62
|
+
var _params_walletProperties, _params_walletProperties_keyShares_;
|
|
63
|
+
const backups = {
|
|
64
|
+
[core.BackupLocation.DYNAMIC]: [],
|
|
65
|
+
[core.BackupLocation.GOOGLE_DRIVE]: [],
|
|
66
|
+
[core.BackupLocation.ICLOUD]: [],
|
|
67
|
+
[core.BackupLocation.USER]: [],
|
|
68
|
+
[core.BackupLocation.EXTERNAL]: []
|
|
69
|
+
};
|
|
70
|
+
if (!(params == null ? void 0 : (_params_walletProperties = params.walletProperties) == null ? void 0 : _params_walletProperties.keyShares)) {
|
|
71
|
+
return {
|
|
72
|
+
backups,
|
|
73
|
+
passwordEncrypted: false
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
params.walletProperties.keyShares.forEach((keyShare)=>{
|
|
77
|
+
if (backups[keyShare.backupLocation]) {
|
|
78
|
+
backups[keyShare.backupLocation].push(keyShare.id);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const passwordEncrypted = Boolean((_params_walletProperties_keyShares_ = params.walletProperties.keyShares[0]) == null ? void 0 : _params_walletProperties_keyShares_.passwordEncrypted);
|
|
82
|
+
return {
|
|
83
|
+
backups,
|
|
84
|
+
passwordEncrypted
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Helper function to merge keyshares and remove duplicates based on pubkey and secretShare
|
|
89
|
+
* @param existingKeyShares - Array of existing keyshares
|
|
90
|
+
* @param newKeyShares - Array of new keyshares to merge
|
|
91
|
+
* @returns Array of merged unique keyshares
|
|
92
|
+
*/ const mergeUniqueKeyShares = (existingKeyShares, newKeyShares)=>{
|
|
93
|
+
const uniqueKeyShares = newKeyShares.filter((newShare)=>!existingKeyShares.some((existingShare)=>{
|
|
94
|
+
if (!(newShare == null ? void 0 : newShare.pubkey) || !(existingShare == null ? void 0 : existingShare.pubkey)) return false;
|
|
95
|
+
return newShare.pubkey.toString() === existingShare.pubkey.toString() && newShare.secretShare === existingShare.secretShare;
|
|
96
|
+
}));
|
|
97
|
+
return [
|
|
98
|
+
...existingKeyShares,
|
|
99
|
+
...uniqueKeyShares
|
|
100
|
+
];
|
|
101
|
+
};
|
|
102
|
+
/**
|
|
103
|
+
* Generic helper function to retry a promise-based operations
|
|
104
|
+
*
|
|
105
|
+
* @param operation - The async operation to retry
|
|
106
|
+
* @param config - Configuration options for retry behavior
|
|
107
|
+
* @returns Promise with the operation result
|
|
108
|
+
* @throws Last error encountered after all retries are exhausted
|
|
109
|
+
*/ async function retryPromise(operation, { maxAttempts = 5, retryInterval = 500, operationName = 'operation', logContext = {} } = {}) {
|
|
110
|
+
let attempts = 0;
|
|
111
|
+
while(attempts < maxAttempts){
|
|
112
|
+
try {
|
|
113
|
+
return await operation();
|
|
114
|
+
} catch (error) {
|
|
115
|
+
attempts++;
|
|
116
|
+
if (attempts === maxAttempts) {
|
|
117
|
+
logger.error(`Failed to execute ${operationName} after ${maxAttempts} attempts`, _extends({}, logContext, {
|
|
118
|
+
error
|
|
119
|
+
}));
|
|
120
|
+
throw error;
|
|
121
|
+
}
|
|
122
|
+
await new Promise((resolve)=>setTimeout(resolve, retryInterval));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// TypeScript needs this even though it's unreachable
|
|
126
|
+
throw new Error('Unreachable code');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const PBKDF2_ALGORITHM = 'PBKDF2';
|
|
130
|
+
const PBKDF2_ITERATIONS = 100000;
|
|
131
|
+
const PBKDF2_HASH_ALGORITHM = 'SHA-256';
|
|
132
|
+
const AES_GCM_ALGORITHM = 'AES-GCM';
|
|
133
|
+
const AES_GCM_LENGTH = 256;
|
|
134
|
+
const getKey = async ({ password, salt })=>{
|
|
135
|
+
const passwordBytes = stringToBytes(password);
|
|
136
|
+
const initialKey = await crypto.subtle.importKey('raw', passwordBytes, {
|
|
137
|
+
name: 'PBKDF2'
|
|
138
|
+
}, false, [
|
|
139
|
+
'deriveKey'
|
|
140
|
+
]);
|
|
141
|
+
return crypto.subtle.deriveKey({
|
|
142
|
+
name: PBKDF2_ALGORITHM,
|
|
143
|
+
salt,
|
|
144
|
+
iterations: PBKDF2_ITERATIONS,
|
|
145
|
+
hash: PBKDF2_HASH_ALGORITHM
|
|
146
|
+
}, initialKey, {
|
|
147
|
+
name: AES_GCM_ALGORITHM,
|
|
148
|
+
length: AES_GCM_LENGTH
|
|
149
|
+
}, false, [
|
|
150
|
+
'encrypt',
|
|
151
|
+
'decrypt'
|
|
152
|
+
]);
|
|
153
|
+
};
|
|
154
|
+
const encryptData = async ({ data, password })=>{
|
|
155
|
+
try {
|
|
156
|
+
// Generate a random salt and IV
|
|
157
|
+
const salt = crypto.getRandomValues(new Uint8Array(16));
|
|
158
|
+
const iv = crypto.getRandomValues(new Uint8Array(12)); // AES-GCM requires 12 bytes
|
|
159
|
+
const key = await getKey({
|
|
160
|
+
password,
|
|
161
|
+
salt
|
|
162
|
+
});
|
|
163
|
+
// Convert the input string to bytes
|
|
164
|
+
const dataBytes = new TextEncoder().encode(data);
|
|
165
|
+
// Encrypt the data
|
|
166
|
+
const encryptedData = await crypto.subtle.encrypt({
|
|
167
|
+
name: AES_GCM_ALGORITHM,
|
|
168
|
+
iv
|
|
169
|
+
}, key, dataBytes);
|
|
170
|
+
// Convert to base64 strings, ensure proper padding
|
|
171
|
+
return {
|
|
172
|
+
salt: bytesToBase64(salt),
|
|
173
|
+
iv: bytesToBase64(iv),
|
|
174
|
+
cipher: bytesToBase64(new Uint8Array(encryptedData))
|
|
175
|
+
};
|
|
176
|
+
} catch (error) {
|
|
177
|
+
throw new Error('Error encrypting data');
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
const decryptData = async ({ data, password })=>{
|
|
181
|
+
try {
|
|
182
|
+
const { salt, iv, cipher } = data;
|
|
183
|
+
// Ensure proper base64 padding for all values
|
|
184
|
+
const paddedSalt = ensureBase64Padding(salt);
|
|
185
|
+
const paddedIv = ensureBase64Padding(iv);
|
|
186
|
+
const paddedCipher = ensureBase64Padding(cipher);
|
|
187
|
+
const saltBytes = base64ToBytes(paddedSalt);
|
|
188
|
+
const ivBytes = base64ToBytes(paddedIv);
|
|
189
|
+
const cipherBytes = base64ToBytes(paddedCipher);
|
|
190
|
+
const key = await getKey({
|
|
191
|
+
password,
|
|
192
|
+
salt: saltBytes
|
|
193
|
+
});
|
|
194
|
+
const decryptedData = await crypto.subtle.decrypt({
|
|
195
|
+
name: AES_GCM_ALGORITHM,
|
|
196
|
+
iv: ivBytes
|
|
197
|
+
}, key, cipherBytes);
|
|
198
|
+
return new TextDecoder().decode(decryptedData);
|
|
199
|
+
} catch (error) {
|
|
200
|
+
throw new Error('Decryption failed');
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const DEFAULT_LOG_LEVEL = 'INFO';
|
|
205
|
+
|
|
206
|
+
class DynamicWalletClient {
|
|
207
|
+
ensureApiClientAuthenticated() {
|
|
208
|
+
if (!this.isApiClientAuthenticated) {
|
|
209
|
+
throw new Error('Client must be authenticated before making API calls. Call authenticateApiToken first.');
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
async authenticateApiToken(authToken) {
|
|
213
|
+
const tmpClient = new core.DynamicApiClient({
|
|
214
|
+
environmentId: this.environmentId,
|
|
215
|
+
authToken,
|
|
216
|
+
baseApiUrl: this.baseApiUrl
|
|
217
|
+
});
|
|
218
|
+
const response = await tmpClient.authenticateApiToken({
|
|
219
|
+
environmentId: this.environmentId
|
|
220
|
+
});
|
|
221
|
+
const jwtTokenAuth = response.data.encodedJwts.minifiedJwt;
|
|
222
|
+
this.baseJWTAuthToken = jwtTokenAuth;
|
|
223
|
+
this.apiClient = new core.DynamicApiClient({
|
|
224
|
+
environmentId: this.environmentId,
|
|
225
|
+
authToken: jwtTokenAuth,
|
|
226
|
+
baseApiUrl: this.baseApiUrl
|
|
227
|
+
});
|
|
228
|
+
this.isApiClientAuthenticated = true;
|
|
229
|
+
}
|
|
230
|
+
async dynamicServerInitializeKeyGen({ chainName, externalServerKeygenIds, thresholdSignatureScheme, onError, onCeremonyComplete }) {
|
|
231
|
+
this.ensureApiClientAuthenticated();
|
|
232
|
+
try {
|
|
233
|
+
const data = await this.apiClient.createWalletAccount({
|
|
234
|
+
chainName,
|
|
235
|
+
clientKeygenIds: externalServerKeygenIds,
|
|
236
|
+
thresholdSignatureScheme,
|
|
237
|
+
onError,
|
|
238
|
+
onCeremonyComplete
|
|
239
|
+
});
|
|
240
|
+
return data;
|
|
241
|
+
} catch (error) {
|
|
242
|
+
this.logger.error('Error in dynamicServerInitializeKeyGen', error);
|
|
243
|
+
throw new Error('Error creating wallet account in dynamicServerInitializeKeyGen');
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
async externalServerInitializeKeyGen({ chainName, thresholdSignatureScheme }) {
|
|
247
|
+
try {
|
|
248
|
+
// Get the mpc signer
|
|
249
|
+
const mpcSigner = getMPCSigner({
|
|
250
|
+
chainName,
|
|
251
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
252
|
+
});
|
|
253
|
+
const clientThreshold = core.getClientThreshold(thresholdSignatureScheme);
|
|
254
|
+
const keygenInitResults = await Promise.all(Array(clientThreshold).fill(null).map(()=>mpcSigner.initKeygen()));
|
|
255
|
+
return keygenInitResults;
|
|
256
|
+
} catch (error) {
|
|
257
|
+
this.logger.error('Error in externalServerInitializeKeyGen', error);
|
|
258
|
+
throw new Error('Error initializing keygen in externalServerInitializeKeyGen');
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
async derivePublicKey({ chainName, keyShare, derivationPath }) {
|
|
262
|
+
try {
|
|
263
|
+
const mpcSigner = getMPCSigner({
|
|
264
|
+
chainName,
|
|
265
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
266
|
+
});
|
|
267
|
+
let publicKey;
|
|
268
|
+
if (mpcSigner instanceof node.Ecdsa) {
|
|
269
|
+
publicKey = await mpcSigner.derivePubkey(keyShare, derivationPath);
|
|
270
|
+
} else if (mpcSigner instanceof node.Ed25519) {
|
|
271
|
+
publicKey = await mpcSigner.derivePubkey(keyShare, derivationPath);
|
|
272
|
+
}
|
|
273
|
+
return publicKey;
|
|
274
|
+
} catch (error) {
|
|
275
|
+
this.logger.error('Error in derivePublicKey', error);
|
|
276
|
+
throw new Error('Error deriving public key in derivePublicKey');
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async externalServerKeyGen({ chainName, roomId, dynamicServerKeygenIds, externalServerInitKeygenResults, thresholdSignatureScheme }) {
|
|
280
|
+
try {
|
|
281
|
+
// Get the chain config and the mpc signer
|
|
282
|
+
const mpcSigner = getMPCSigner({
|
|
283
|
+
chainName,
|
|
284
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
285
|
+
});
|
|
286
|
+
// Get the MPC config for the threshold signature scheme
|
|
287
|
+
const mpcConfig = core.MPC_CONFIG[thresholdSignatureScheme];
|
|
288
|
+
// For each client keygen init result, create an array of other parties' keygenIds
|
|
289
|
+
const serverKeygenResults = await Promise.all(externalServerInitKeygenResults.map((currentInit)=>{
|
|
290
|
+
// Get all other client keygenIds (excluding current one)
|
|
291
|
+
const otherExternalServerKeygenIds = externalServerInitKeygenResults.filter((init)=>init.keygenId !== currentInit.keygenId).map((init)=>init.keygenId);
|
|
292
|
+
// Combine server keygenIds with other client keygenIds
|
|
293
|
+
const allOtherKeygenIds = [
|
|
294
|
+
...dynamicServerKeygenIds,
|
|
295
|
+
...otherExternalServerKeygenIds
|
|
296
|
+
];
|
|
297
|
+
return mpcSigner.keygen(roomId, mpcConfig.numberOfParties, mpcConfig.threshold, currentInit, allOtherKeygenIds);
|
|
298
|
+
}));
|
|
299
|
+
// only need one client keygen result to derive the public key
|
|
300
|
+
const [serverKeygenResult] = serverKeygenResults;
|
|
301
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
302
|
+
const derivationPath = new Uint32Array(chainConfig.derivationPath);
|
|
303
|
+
const rawPublicKey = await this.derivePublicKey({
|
|
304
|
+
chainName,
|
|
305
|
+
keyShare: serverKeygenResult,
|
|
306
|
+
derivationPath
|
|
307
|
+
});
|
|
308
|
+
return {
|
|
309
|
+
rawPublicKey,
|
|
310
|
+
externalServerKeyGenResults: serverKeygenResults
|
|
311
|
+
};
|
|
312
|
+
} catch (error) {
|
|
313
|
+
this.logger.error('Error in externalServerKeyGen', error);
|
|
314
|
+
throw new Error('Error deriving public key in externalServerKeyGen');
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
async keyGen({ chainName, thresholdSignatureScheme, onError, onCeremonyComplete }) {
|
|
318
|
+
try {
|
|
319
|
+
const externalServerInitKeygenResults = await this.externalServerInitializeKeyGen({
|
|
320
|
+
chainName,
|
|
321
|
+
thresholdSignatureScheme
|
|
322
|
+
});
|
|
323
|
+
const externalServerKeygenIds = externalServerInitKeygenResults.map((result)=>result.keygenId);
|
|
324
|
+
const { roomId, serverKeygenIds: dynamicServerKeygenIds } = await this.dynamicServerInitializeKeyGen({
|
|
325
|
+
chainName,
|
|
326
|
+
externalServerKeygenIds,
|
|
327
|
+
thresholdSignatureScheme,
|
|
328
|
+
onCeremonyComplete
|
|
329
|
+
});
|
|
330
|
+
const { rawPublicKey, externalServerKeyGenResults } = await this.externalServerKeyGen({
|
|
331
|
+
chainName,
|
|
332
|
+
roomId,
|
|
333
|
+
dynamicServerKeygenIds,
|
|
334
|
+
externalServerInitKeygenResults,
|
|
335
|
+
thresholdSignatureScheme
|
|
336
|
+
});
|
|
337
|
+
return {
|
|
338
|
+
rawPublicKey,
|
|
339
|
+
externalServerKeyShares: externalServerKeyGenResults
|
|
340
|
+
};
|
|
341
|
+
} catch (error) {
|
|
342
|
+
this.logger.error('Error in keyGen', error);
|
|
343
|
+
throw new Error('Error creating wallet account in keyGen');
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
async importRawPrivateKey({ chainName, privateKey, thresholdSignatureScheme, onError, onCeremonyComplete }) {
|
|
347
|
+
this.ensureApiClientAuthenticated();
|
|
348
|
+
const mpcSigner = getMPCSigner({
|
|
349
|
+
chainName,
|
|
350
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
351
|
+
});
|
|
352
|
+
const externalServerKeygenInitResults = await this.externalServerInitializeKeyGen({
|
|
353
|
+
chainName,
|
|
354
|
+
thresholdSignatureScheme
|
|
355
|
+
});
|
|
356
|
+
const externalServerKeygenIds = externalServerKeygenInitResults.map((result)=>result.keygenId);
|
|
357
|
+
const { roomId, serverKeygenIds: dynamicServerKeygenIds } = await this.apiClient.importPrivateKey({
|
|
358
|
+
chainName,
|
|
359
|
+
clientKeygenIds: externalServerKeygenIds,
|
|
360
|
+
thresholdSignatureScheme,
|
|
361
|
+
onError,
|
|
362
|
+
onCeremonyComplete
|
|
363
|
+
});
|
|
364
|
+
const { threshold } = core.getTSSConfig(thresholdSignatureScheme);
|
|
365
|
+
const externalServerKeygenResults = await Promise.all(externalServerKeygenInitResults.map(async (currentInit, index)=>{
|
|
366
|
+
const otherExternalServerKeygenIds = externalServerKeygenInitResults.filter((init)=>init.keygenId !== currentInit.keygenId).map((init)=>init.keygenId);
|
|
367
|
+
if (index === 0) {
|
|
368
|
+
const otherKeyGenIds = [
|
|
369
|
+
...dynamicServerKeygenIds,
|
|
370
|
+
...otherExternalServerKeygenIds
|
|
371
|
+
];
|
|
372
|
+
const importerKeygenResult = await mpcSigner.importPrivateKeyImporter(roomId, threshold, privateKey, currentInit, otherKeyGenIds);
|
|
373
|
+
return importerKeygenResult;
|
|
374
|
+
} else {
|
|
375
|
+
const recipientKeygenResult = await mpcSigner.importPrivateKeyRecipient(roomId, threshold, currentInit, [
|
|
376
|
+
...dynamicServerKeygenIds,
|
|
377
|
+
...otherExternalServerKeygenIds
|
|
378
|
+
]);
|
|
379
|
+
return recipientKeygenResult;
|
|
380
|
+
}
|
|
381
|
+
}));
|
|
382
|
+
const [externalServerKeygenResult] = externalServerKeygenResults;
|
|
383
|
+
const rawPublicKey = await this.derivePublicKey({
|
|
384
|
+
chainName,
|
|
385
|
+
keyShare: externalServerKeygenResult,
|
|
386
|
+
derivationPath: undefined
|
|
387
|
+
});
|
|
388
|
+
return {
|
|
389
|
+
rawPublicKey,
|
|
390
|
+
externalServerKeyShares: externalServerKeygenResults
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
async dynamicServerSign({ walletId, message }) {
|
|
394
|
+
this.ensureApiClientAuthenticated();
|
|
395
|
+
// Create the room and sign the message
|
|
396
|
+
if (typeof message !== 'string') {
|
|
397
|
+
message = '0x' + Buffer.from(message).toString('hex');
|
|
398
|
+
}
|
|
399
|
+
const data = await this.apiClient.signMessage({
|
|
400
|
+
walletId,
|
|
401
|
+
message
|
|
402
|
+
});
|
|
403
|
+
return data;
|
|
404
|
+
}
|
|
405
|
+
async externalServerSign({ chainName, message, roomId, keyShare, derivationPath }) {
|
|
406
|
+
try {
|
|
407
|
+
const mpcSigner = getMPCSigner({
|
|
408
|
+
chainName,
|
|
409
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
410
|
+
});
|
|
411
|
+
let formattedMessage;
|
|
412
|
+
//note: Ecdsa can also be used by bitcoin, but only keccak256 is used by ethereum
|
|
413
|
+
if (mpcSigner instanceof node.Ecdsa) {
|
|
414
|
+
formattedMessage = node.MessageHash.keccak256(message);
|
|
415
|
+
} else if (mpcSigner instanceof node.Ed25519) {
|
|
416
|
+
if (typeof message === 'string') {
|
|
417
|
+
if (!isHexString(message)) {
|
|
418
|
+
formattedMessage = Buffer.from(message).toString('hex');
|
|
419
|
+
} else {
|
|
420
|
+
formattedMessage = Buffer.from(message, 'hex');
|
|
421
|
+
}
|
|
422
|
+
} else {
|
|
423
|
+
formattedMessage = message;
|
|
424
|
+
}
|
|
425
|
+
} else if (mpcSigner instanceof node.BIP340 && typeof message === 'string') {
|
|
426
|
+
formattedMessage = new TextEncoder().encode(message);
|
|
427
|
+
} else {
|
|
428
|
+
throw new Error('Unsupported signer type');
|
|
429
|
+
}
|
|
430
|
+
const signature = await mpcSigner.sign(roomId, keyShare, formattedMessage, derivationPath);
|
|
431
|
+
return signature;
|
|
432
|
+
} catch (error) {
|
|
433
|
+
this.logger.error('Error in externalServerSign', error);
|
|
434
|
+
throw error;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
//todo: need to modify with imported flag
|
|
438
|
+
async sign({ accountAddress, message, chainName, password = undefined }) {
|
|
439
|
+
await this.verifyPassword({
|
|
440
|
+
accountAddress,
|
|
441
|
+
password,
|
|
442
|
+
walletOperation: core.WalletOperation.SIGN_MESSAGE
|
|
443
|
+
});
|
|
444
|
+
const wallet = await this.getWallet({
|
|
445
|
+
accountAddress,
|
|
446
|
+
walletOperation: core.WalletOperation.SIGN_MESSAGE,
|
|
447
|
+
password
|
|
448
|
+
});
|
|
449
|
+
// Perform the dynamic server sign
|
|
450
|
+
const data = await this.dynamicServerSign({
|
|
451
|
+
walletId: wallet.walletId,
|
|
452
|
+
message
|
|
453
|
+
});
|
|
454
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
455
|
+
// Perform the external server sign and return the signature
|
|
456
|
+
const signature = await this.externalServerSign({
|
|
457
|
+
chainName,
|
|
458
|
+
message,
|
|
459
|
+
roomId: data.roomId,
|
|
460
|
+
keyShare: wallet.externalServerKeyShares[0],
|
|
461
|
+
derivationPath
|
|
462
|
+
});
|
|
463
|
+
return signature;
|
|
464
|
+
}
|
|
465
|
+
async refreshWalletAccountShares({ accountAddress, chainName, password = undefined }) {
|
|
466
|
+
this.ensureApiClientAuthenticated();
|
|
467
|
+
await this.verifyPassword({
|
|
468
|
+
accountAddress,
|
|
469
|
+
password,
|
|
470
|
+
walletOperation: core.WalletOperation.REFRESH
|
|
471
|
+
});
|
|
472
|
+
const wallet = await this.getWallet({
|
|
473
|
+
accountAddress,
|
|
474
|
+
walletOperation: core.WalletOperation.REFRESH,
|
|
475
|
+
password
|
|
476
|
+
});
|
|
477
|
+
const mpcSigner = getMPCSigner({
|
|
478
|
+
chainName,
|
|
479
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
480
|
+
});
|
|
481
|
+
// Create the room and refresh the shares
|
|
482
|
+
const data = await this.apiClient.refreshWalletAccountShares({
|
|
483
|
+
walletId: wallet.walletId
|
|
484
|
+
});
|
|
485
|
+
const roomId = data.roomId;
|
|
486
|
+
const refreshResults = await Promise.all(wallet.externalServerKeyShares.map((serverKeyShare)=>mpcSigner.refresh(roomId, serverKeyShare)));
|
|
487
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
488
|
+
externalServerKeyShares: refreshResults,
|
|
489
|
+
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
|
|
490
|
+
});
|
|
491
|
+
await this.storeEncryptedBackupByWallet({
|
|
492
|
+
accountAddress,
|
|
493
|
+
password: password != null ? password : this.environmentId
|
|
494
|
+
});
|
|
495
|
+
return refreshResults;
|
|
496
|
+
}
|
|
497
|
+
async getExportId({ chainName, serverKeyShare }) {
|
|
498
|
+
const mpcSigner = getMPCSigner({
|
|
499
|
+
chainName,
|
|
500
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
501
|
+
});
|
|
502
|
+
const exportId = await mpcSigner.exportID(serverKeyShare);
|
|
503
|
+
return exportId;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Helper function to create client shares required to complete a reshare ceremony.
|
|
507
|
+
* @param {string} chainName - The chain to create shares for
|
|
508
|
+
* @param {WalletProperties} wallet - The wallet to reshare
|
|
509
|
+
* @param {ThresholdSignatureScheme} oldThresholdSignatureScheme - The current threshold signature scheme
|
|
510
|
+
* @param {ThresholdSignatureScheme} newThresholdSignatureScheme - The target threshold signature scheme
|
|
511
|
+
* @returns {Promise<{
|
|
512
|
+
* newClientInitKeygenResults: ClientInitKeygenResult[],
|
|
513
|
+
* newClientKeygenIds: string[],
|
|
514
|
+
* existingClientKeygenIds: string[],
|
|
515
|
+
* existingClientKeyShares: ClientKeyShare[]
|
|
516
|
+
* }>} Object containing new and existing client keygen results, IDs and shares
|
|
517
|
+
* @todo Support higher to lower reshare strategies
|
|
518
|
+
*/ async reshareStrategy({ chainName, wallet, oldThresholdSignatureScheme, newThresholdSignatureScheme }) {
|
|
519
|
+
const mpcSigner = getMPCSigner({
|
|
520
|
+
chainName,
|
|
521
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
522
|
+
});
|
|
523
|
+
// Determine share counts based on threshold signature schemes
|
|
524
|
+
const { newExternalServerShareCount, existingExternalServerShareCount } = core.getServerWalletReshareConfig({
|
|
525
|
+
oldThresholdSignatureScheme,
|
|
526
|
+
newThresholdSignatureScheme
|
|
527
|
+
});
|
|
528
|
+
// Create new client shares
|
|
529
|
+
const newExternalServerInitKeygenResults = await Promise.all(Array.from({
|
|
530
|
+
length: newExternalServerShareCount
|
|
531
|
+
}, ()=>mpcSigner.initKeygen()));
|
|
532
|
+
const newExternalServerKeygenIds = newExternalServerInitKeygenResults.map((result)=>result.keygenId);
|
|
533
|
+
// Get existing client shares
|
|
534
|
+
const existingExternalServerKeyShares = wallet.externalServerKeyShares.slice(0, existingExternalServerShareCount);
|
|
535
|
+
const existingExternalServerKeygenIds = await Promise.all(existingExternalServerKeyShares.map(async (keyShare)=>await this.getExportId({
|
|
536
|
+
chainName,
|
|
537
|
+
serverKeyShare: keyShare
|
|
538
|
+
})));
|
|
539
|
+
return {
|
|
540
|
+
newExternalServerInitKeygenResults,
|
|
541
|
+
newExternalServerKeygenIds,
|
|
542
|
+
existingExternalServerKeygenIds,
|
|
543
|
+
existingExternalServerKeyShares
|
|
544
|
+
};
|
|
545
|
+
}
|
|
546
|
+
async reshare({ chainName, accountAddress, oldThresholdSignatureScheme, newThresholdSignatureScheme, password = undefined }) {
|
|
547
|
+
this.ensureApiClientAuthenticated();
|
|
548
|
+
await this.verifyPassword({
|
|
549
|
+
accountAddress,
|
|
550
|
+
password,
|
|
551
|
+
walletOperation: core.WalletOperation.RESHARE
|
|
552
|
+
});
|
|
553
|
+
const { existingExternalServerShareCount } = core.getServerWalletReshareConfig({
|
|
554
|
+
oldThresholdSignatureScheme,
|
|
555
|
+
newThresholdSignatureScheme
|
|
556
|
+
});
|
|
557
|
+
const wallet = await this.getWallet({
|
|
558
|
+
accountAddress,
|
|
559
|
+
walletOperation: core.WalletOperation.RESHARE,
|
|
560
|
+
shareCount: existingExternalServerShareCount,
|
|
561
|
+
password
|
|
562
|
+
});
|
|
563
|
+
const { newExternalServerInitKeygenResults, newExternalServerKeygenIds, existingExternalServerKeygenIds, existingExternalServerKeyShares } = await this.reshareStrategy({
|
|
564
|
+
chainName,
|
|
565
|
+
wallet,
|
|
566
|
+
oldThresholdSignatureScheme,
|
|
567
|
+
newThresholdSignatureScheme
|
|
568
|
+
});
|
|
569
|
+
const externalServerKeygenIds = [
|
|
570
|
+
...newExternalServerKeygenIds,
|
|
571
|
+
...existingExternalServerKeygenIds
|
|
572
|
+
];
|
|
573
|
+
// Server to create the room and complete the server reshare logics
|
|
574
|
+
const data = await this.apiClient.reshare({
|
|
575
|
+
walletId: wallet.walletId,
|
|
576
|
+
clientKeygenIds: externalServerKeygenIds,
|
|
577
|
+
oldThresholdSignatureScheme,
|
|
578
|
+
newThresholdSignatureScheme
|
|
579
|
+
});
|
|
580
|
+
const { roomId, serverKeygenIds: dynamicServerKeygenIds, newServerKeygenIds: newDynamicServerKeygenIds = [] } = data;
|
|
581
|
+
// Get the MPC config for the threshold signature scheme
|
|
582
|
+
const oldMpcConfig = core.MPC_CONFIG[oldThresholdSignatureScheme];
|
|
583
|
+
const newMpcConfig = core.MPC_CONFIG[newThresholdSignatureScheme];
|
|
584
|
+
const allPartyKeygenIds = [
|
|
585
|
+
...externalServerKeygenIds,
|
|
586
|
+
...dynamicServerKeygenIds,
|
|
587
|
+
...newDynamicServerKeygenIds
|
|
588
|
+
];
|
|
589
|
+
const mpcSigner = getMPCSigner({
|
|
590
|
+
chainName,
|
|
591
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
592
|
+
});
|
|
593
|
+
const reshareResults = await Promise.all([
|
|
594
|
+
...newExternalServerInitKeygenResults.map((keygenResult)=>mpcSigner.reshareNewParty(roomId, oldMpcConfig.threshold, newMpcConfig.threshold, keygenResult, allPartyKeygenIds)),
|
|
595
|
+
...existingExternalServerKeyShares.map((keyShare)=>mpcSigner.reshareRemainingParty(roomId, newMpcConfig.threshold, keyShare, allPartyKeygenIds))
|
|
596
|
+
]);
|
|
597
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
598
|
+
externalServerKeyShares: reshareResults,
|
|
599
|
+
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo()
|
|
600
|
+
});
|
|
601
|
+
await this.storeEncryptedBackupByWallet({
|
|
602
|
+
accountAddress,
|
|
603
|
+
password
|
|
604
|
+
});
|
|
605
|
+
return reshareResults;
|
|
606
|
+
}
|
|
607
|
+
async exportKey({ accountAddress, chainName, password = undefined }) {
|
|
608
|
+
this.ensureApiClientAuthenticated();
|
|
609
|
+
await this.verifyPassword({
|
|
610
|
+
accountAddress,
|
|
611
|
+
password,
|
|
612
|
+
walletOperation: core.WalletOperation.EXPORT_PRIVATE_KEY
|
|
613
|
+
});
|
|
614
|
+
const wallet = await this.getWallet({
|
|
615
|
+
accountAddress,
|
|
616
|
+
password,
|
|
617
|
+
walletOperation: core.WalletOperation.EXPORT_PRIVATE_KEY
|
|
618
|
+
});
|
|
619
|
+
const mpcSigner = getMPCSigner({
|
|
620
|
+
chainName,
|
|
621
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
622
|
+
});
|
|
623
|
+
const exportId = await this.getExportId({
|
|
624
|
+
chainName,
|
|
625
|
+
serverKeyShare: wallet.externalServerKeyShares[0]
|
|
626
|
+
});
|
|
627
|
+
const data = await this.apiClient.exportKey({
|
|
628
|
+
walletId: wallet.walletId,
|
|
629
|
+
exportId
|
|
630
|
+
});
|
|
631
|
+
const keyExportRaw = await mpcSigner.exportFullPrivateKey(data.roomId, wallet.externalServerKeyShares[0], exportId);
|
|
632
|
+
if (!keyExportRaw) {
|
|
633
|
+
throw new Error('Error exporting private key');
|
|
634
|
+
}
|
|
635
|
+
const derivationPath = wallet.derivationPath && wallet.derivationPath != '' ? new Uint32Array(Object.values(JSON.parse(wallet.derivationPath))) : undefined;
|
|
636
|
+
let derivedPrivateKey;
|
|
637
|
+
if (mpcSigner instanceof node.Ecdsa) {
|
|
638
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
639
|
+
} else if (mpcSigner instanceof node.Ed25519) {
|
|
640
|
+
derivedPrivateKey = keyExportRaw;
|
|
641
|
+
} else if (mpcSigner instanceof node.BIP340) {
|
|
642
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, derivationPath);
|
|
643
|
+
}
|
|
644
|
+
return {
|
|
645
|
+
derivedPrivateKey
|
|
646
|
+
};
|
|
647
|
+
}
|
|
648
|
+
async offlineExportKey({ chainName, keyShares, derivationPath }) {
|
|
649
|
+
try {
|
|
650
|
+
if (!keyShares || keyShares.length < 2) {
|
|
651
|
+
throw new Error(`Must provide at least min threshold of key shares`);
|
|
652
|
+
}
|
|
653
|
+
const mpcSigner = getMPCSigner({
|
|
654
|
+
chainName,
|
|
655
|
+
baseRelayUrl: this.baseMPCRelayApiUrl
|
|
656
|
+
});
|
|
657
|
+
const walletKeyShares = keyShares.map((keyShare)=>{
|
|
658
|
+
return mpcSigner instanceof node.Ecdsa ? new node.EcdsaKeygenResult(keyShare.pubkey, keyShare.secretShare) : mpcSigner instanceof node.Ed25519 ? new node.Ed25519KeygenResult(keyShare.pubkey, keyShare.secretShare) : new node.BIP340KeygenResult(keyShare.pubkey, keyShare.secretShare);
|
|
659
|
+
});
|
|
660
|
+
const keyExportRaw = await mpcSigner.offlineExportFullPrivateKey(walletKeyShares);
|
|
661
|
+
if (!keyExportRaw) {
|
|
662
|
+
throw new Error('Error exporting private key: Export returned null');
|
|
663
|
+
}
|
|
664
|
+
const chainConfig = core.getMPCChainConfig(chainName);
|
|
665
|
+
const walletDerivationPath = !derivationPath ? undefined : new Uint32Array(chainConfig.derivationPath);
|
|
666
|
+
let derivedPrivateKey;
|
|
667
|
+
if (mpcSigner instanceof node.Ecdsa) {
|
|
668
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, walletDerivationPath);
|
|
669
|
+
} else if (mpcSigner instanceof node.Ed25519) {
|
|
670
|
+
derivedPrivateKey = keyExportRaw;
|
|
671
|
+
} else if (mpcSigner instanceof node.BIP340) {
|
|
672
|
+
derivedPrivateKey = await mpcSigner.derivePrivateKeyFromXpriv(keyExportRaw, walletDerivationPath);
|
|
673
|
+
}
|
|
674
|
+
return {
|
|
675
|
+
derivedPrivateKey
|
|
676
|
+
};
|
|
677
|
+
} catch (error) {
|
|
678
|
+
this.logger.error('Error in offlineExportKey:', error);
|
|
679
|
+
throw error;
|
|
680
|
+
}
|
|
681
|
+
}
|
|
682
|
+
async encryptKeyShare({ keyShare, password }) {
|
|
683
|
+
const serializedKeyShare = JSON.stringify(keyShare);
|
|
684
|
+
const encryptedKeyShare = await encryptData({
|
|
685
|
+
data: serializedKeyShare,
|
|
686
|
+
password: password != null ? password : this.environmentId
|
|
687
|
+
});
|
|
688
|
+
// stringify the encrypted key share, convert to base64, and store it
|
|
689
|
+
const serializedEncryptedKeyShare = Buffer.from(JSON.stringify(encryptedKeyShare)).toString('base64');
|
|
690
|
+
return serializedEncryptedKeyShare;
|
|
691
|
+
}
|
|
692
|
+
async ensureCeremonyCompletionBeforeBackup({ accountAddress }) {
|
|
693
|
+
let retries = 0;
|
|
694
|
+
const maxRetries = 3;
|
|
695
|
+
while((!this.walletMap[accountAddress] || !this.walletMap[accountAddress].walletId) && retries < maxRetries){
|
|
696
|
+
await new Promise((resolve)=>setTimeout(resolve, 1000)); // Wait 1 second
|
|
697
|
+
retries++;
|
|
698
|
+
}
|
|
699
|
+
if (!this.walletMap[accountAddress] || !this.walletMap[accountAddress].walletId) {
|
|
700
|
+
throw new Error('Ceremony completion timeout');
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
async storeEncryptedBackupByWallet({ accountAddress, externalServerKeyShares = undefined, password = undefined }) {
|
|
704
|
+
this.ensureApiClientAuthenticated();
|
|
705
|
+
//add retry logic for ceremony completion to prevent race condition
|
|
706
|
+
await this.ensureCeremonyCompletionBeforeBackup({
|
|
707
|
+
accountAddress
|
|
708
|
+
});
|
|
709
|
+
try {
|
|
710
|
+
const keySharesToBackup = externalServerKeyShares != null ? externalServerKeyShares : await this.getExternalServerKeyShares({
|
|
711
|
+
accountAddress
|
|
712
|
+
});
|
|
713
|
+
if (!keySharesToBackup || keySharesToBackup.length === 0) {
|
|
714
|
+
throw new Error(`Key shares not found for accountAddress: ${accountAddress}`);
|
|
715
|
+
}
|
|
716
|
+
const encryptedKeyShares = await Promise.all(keySharesToBackup.map((keyShare)=>this.encryptKeyShare({
|
|
717
|
+
keyShare,
|
|
718
|
+
password
|
|
719
|
+
})));
|
|
720
|
+
if (!this.walletMap[accountAddress] || !this.walletMap[accountAddress].walletId) {
|
|
721
|
+
throw new Error(`WalletId not found for accountAddress: ${accountAddress}`);
|
|
722
|
+
}
|
|
723
|
+
const data = await this.apiClient.storeEncryptedBackupByWallet({
|
|
724
|
+
walletId: this.walletMap[accountAddress].walletId,
|
|
725
|
+
encryptedKeyShares,
|
|
726
|
+
passwordEncrypted: Boolean(password) && password !== this.environmentId
|
|
727
|
+
});
|
|
728
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
729
|
+
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo({
|
|
730
|
+
walletProperties: {
|
|
731
|
+
derivationPath: this.walletMap[accountAddress].derivationPath,
|
|
732
|
+
keyShares: data.keyShares,
|
|
733
|
+
thresholdSignatureScheme: this.walletMap[accountAddress].thresholdSignatureScheme
|
|
734
|
+
}
|
|
735
|
+
})
|
|
736
|
+
});
|
|
737
|
+
return data;
|
|
738
|
+
} catch (error) {
|
|
739
|
+
this.logger.error('Error in storeEncryptedBackupByWallet:', error);
|
|
740
|
+
throw error;
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
async storeEncryptedBackupByWalletWithRetry({ accountAddress, externalServerKeyShares, password }) {
|
|
744
|
+
await retryPromise(()=>this.storeEncryptedBackupByWallet({
|
|
745
|
+
accountAddress,
|
|
746
|
+
externalServerKeyShares,
|
|
747
|
+
password
|
|
748
|
+
}), {
|
|
749
|
+
operationName: 'store encrypted backup',
|
|
750
|
+
logContext: {
|
|
751
|
+
walletAddress: accountAddress,
|
|
752
|
+
keyShares: externalServerKeyShares == null ? void 0 : externalServerKeyShares.map((keyShare)=>this.encryptKeyShare({
|
|
753
|
+
keyShare,
|
|
754
|
+
password
|
|
755
|
+
}))
|
|
756
|
+
}
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
async getExternalServerKeyShares({ accountAddress, password }) {
|
|
760
|
+
const wallet = await this.getWallet({
|
|
761
|
+
accountAddress,
|
|
762
|
+
password,
|
|
763
|
+
walletOperation: core.WalletOperation.REACH_THRESHOLD
|
|
764
|
+
});
|
|
765
|
+
return wallet.externalServerKeyShares;
|
|
766
|
+
}
|
|
767
|
+
async updatePassword({ accountAddress, existingPassword, newPassword }) {
|
|
768
|
+
await this.getWallet({
|
|
769
|
+
accountAddress,
|
|
770
|
+
password: existingPassword,
|
|
771
|
+
walletOperation: core.WalletOperation.REACH_ALL_PARTIES
|
|
772
|
+
});
|
|
773
|
+
await this.storeEncryptedBackupByWallet({
|
|
774
|
+
accountAddress,
|
|
775
|
+
password: newPassword
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
async decryptKeyShare({ keyShare, password }) {
|
|
779
|
+
const decodedKeyShare = JSON.parse(Buffer.from(keyShare, 'base64').toString());
|
|
780
|
+
const decryptedKeyShare = await decryptData({
|
|
781
|
+
data: decodedKeyShare,
|
|
782
|
+
password: password != null ? password : this.environmentId
|
|
783
|
+
});
|
|
784
|
+
const deserializedKeyShare = JSON.parse(decryptedKeyShare);
|
|
785
|
+
return deserializedKeyShare;
|
|
786
|
+
}
|
|
787
|
+
/**
|
|
788
|
+
* Helper function to determine keyshare recovery strategy for dynamic shares.
|
|
789
|
+
* For REFRESH operations, retrieves enough shares to meet the client threshold.
|
|
790
|
+
* For all other operations, retrieves just 1 share.
|
|
791
|
+
*
|
|
792
|
+
* @param clientKeyShareBackupInfo - Information about backed up key shares
|
|
793
|
+
* @param thresholdSignatureScheme - The signature scheme being used (2-of-2, 2-of-3, etc)
|
|
794
|
+
* @param walletOperation - The operation being performed (REFRESH, SIGN_MESSAGE, etc)
|
|
795
|
+
* @param shareCount - The number of shares to recover if specified for reshare operations
|
|
796
|
+
* @returns @shares: Object mapping backup locations to arrays of share IDs to recover
|
|
797
|
+
* @returns @requiredShareCount: The number of shares required to recover
|
|
798
|
+
*/ recoverStrategy({ externalServerKeySharesBackupInfo, thresholdSignatureScheme, walletOperation, shareCount = undefined }) {
|
|
799
|
+
const { backups } = externalServerKeySharesBackupInfo;
|
|
800
|
+
const { clientThreshold } = core.MPC_CONFIG[thresholdSignatureScheme];
|
|
801
|
+
let requiredShareCount = walletOperation === core.WalletOperation.REFRESH || walletOperation === core.WalletOperation.REACH_ALL_PARTIES || walletOperation === core.WalletOperation.RESHARE ? clientThreshold : 1;
|
|
802
|
+
// Override requiredShareCount if shareCount is provided
|
|
803
|
+
if (shareCount !== undefined) {
|
|
804
|
+
requiredShareCount = shareCount;
|
|
805
|
+
}
|
|
806
|
+
const dynamicShares = backups[core.BackupLocation.DYNAMIC].slice(0, requiredShareCount);
|
|
807
|
+
return {
|
|
808
|
+
shares: {
|
|
809
|
+
[core.BackupLocation.DYNAMIC]: dynamicShares
|
|
810
|
+
},
|
|
811
|
+
requiredShareCount
|
|
812
|
+
};
|
|
813
|
+
}
|
|
814
|
+
async recoverEncryptedBackupByWallet({ accountAddress, password, walletOperation, shareCount = undefined, storeRecoveredShares = true }) {
|
|
815
|
+
this.ensureApiClientAuthenticated();
|
|
816
|
+
const wallet = this.walletMap[accountAddress];
|
|
817
|
+
this.logger.debug(`recoverEncryptedBackupByWallet wallet: ${walletOperation}`, wallet);
|
|
818
|
+
const { shares } = this.recoverStrategy({
|
|
819
|
+
externalServerKeySharesBackupInfo: wallet.externalServerKeySharesBackupInfo,
|
|
820
|
+
thresholdSignatureScheme: wallet.thresholdSignatureScheme,
|
|
821
|
+
walletOperation,
|
|
822
|
+
shareCount
|
|
823
|
+
});
|
|
824
|
+
const { dynamic: dynamicKeyShareIds } = shares;
|
|
825
|
+
const data = await this.apiClient.recoverEncryptedBackupByWallet({
|
|
826
|
+
walletId: wallet.walletId,
|
|
827
|
+
keyShareIds: dynamicKeyShareIds
|
|
828
|
+
});
|
|
829
|
+
const dynamicKeyShares = data.keyShares.filter((keyShare)=>keyShare.encryptedAccountCredential !== null && keyShare.backupLocation === core.BackupLocation.DYNAMIC);
|
|
830
|
+
const decryptedKeyShares = await Promise.all(dynamicKeyShares.map((keyShare)=>this.decryptKeyShare({
|
|
831
|
+
keyShare: keyShare.encryptedAccountCredential,
|
|
832
|
+
password: password != null ? password : this.environmentId
|
|
833
|
+
})));
|
|
834
|
+
if (storeRecoveredShares) {
|
|
835
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
836
|
+
externalServerKeyShares: mergeUniqueKeyShares(this.walletMap[accountAddress].externalServerKeyShares || [], decryptedKeyShares)
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
return decryptedKeyShares;
|
|
840
|
+
}
|
|
841
|
+
async exportExternalServerKeyShares({ accountAddress, password }) {
|
|
842
|
+
await this.verifyPassword({
|
|
843
|
+
accountAddress,
|
|
844
|
+
password,
|
|
845
|
+
walletOperation: core.WalletOperation.REACH_ALL_PARTIES
|
|
846
|
+
});
|
|
847
|
+
const externalServerKeyShares = await this.getExternalServerKeyShares({
|
|
848
|
+
accountAddress,
|
|
849
|
+
password
|
|
850
|
+
});
|
|
851
|
+
return externalServerKeyShares;
|
|
852
|
+
}
|
|
853
|
+
/**
|
|
854
|
+
* Helper function to check if the required wallet fields are present and valid
|
|
855
|
+
* @param accountAddress - The account address of the wallet to check
|
|
856
|
+
* @param walletOperation - The wallet operation that determines required fields
|
|
857
|
+
* @returns boolean indicating if wallet needs to be re-fetched and restored from server
|
|
858
|
+
*/ async checkWalletFields({ accountAddress, walletOperation = core.WalletOperation.REACH_THRESHOLD, shareCount }) {
|
|
859
|
+
let keyshareCheck = false;
|
|
860
|
+
let walletCheck = false;
|
|
861
|
+
let thresholdSignatureSchemeCheck = false;
|
|
862
|
+
let derivationPathCheck = false;
|
|
863
|
+
// check if wallet exists
|
|
864
|
+
const existingWallet = this.walletMap[accountAddress];
|
|
865
|
+
if (existingWallet) {
|
|
866
|
+
walletCheck = true;
|
|
867
|
+
}
|
|
868
|
+
// check if threshold signature scheme exists
|
|
869
|
+
if (existingWallet == null ? void 0 : existingWallet.thresholdSignatureScheme) {
|
|
870
|
+
thresholdSignatureSchemeCheck = true;
|
|
871
|
+
}
|
|
872
|
+
// check if derivation path exists
|
|
873
|
+
if ((existingWallet == null ? void 0 : existingWallet.derivationPath) || (existingWallet == null ? void 0 : existingWallet.derivationPath) === '') {
|
|
874
|
+
derivationPathCheck = true;
|
|
875
|
+
}
|
|
876
|
+
// check if wallet already exists with sufficient keyshares
|
|
877
|
+
if (existingWallet) {
|
|
878
|
+
var _existingWallet_externalServerKeyShares;
|
|
879
|
+
const { shares } = this.recoverStrategy({
|
|
880
|
+
externalServerKeySharesBackupInfo: existingWallet.externalServerKeySharesBackupInfo || {
|
|
881
|
+
backups: getExternalServerKeyShareBackupInfo()
|
|
882
|
+
},
|
|
883
|
+
thresholdSignatureScheme: existingWallet.thresholdSignatureScheme,
|
|
884
|
+
walletOperation,
|
|
885
|
+
shareCount
|
|
886
|
+
});
|
|
887
|
+
const { dynamic: requiredDynamicKeyShareIds = [] } = shares;
|
|
888
|
+
if (requiredDynamicKeyShareIds.length <= (((_existingWallet_externalServerKeyShares = existingWallet.externalServerKeyShares) == null ? void 0 : _existingWallet_externalServerKeyShares.length) || 0)) {
|
|
889
|
+
keyshareCheck = true;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
return walletCheck && thresholdSignatureSchemeCheck && keyshareCheck && derivationPathCheck;
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* verifyPassword attempts to recover and decrypt a single client key share using the provided password.
|
|
896
|
+
* If successful, the key share is encrypted with the new password. This method solely performs the recovery
|
|
897
|
+
* and decryption without storing the restored key shares. If unsuccessful, it throws an error.
|
|
898
|
+
*/ async verifyPassword({ accountAddress, password = undefined, walletOperation = core.WalletOperation.NO_OPERATION }) {
|
|
899
|
+
await this.getWallet({
|
|
900
|
+
accountAddress,
|
|
901
|
+
password,
|
|
902
|
+
walletOperation
|
|
903
|
+
});
|
|
904
|
+
if (await this.requiresPasswordForOperation({
|
|
905
|
+
accountAddress,
|
|
906
|
+
walletOperation
|
|
907
|
+
}) && !password) {
|
|
908
|
+
throw new Error('Password is required for operation but not provided');
|
|
909
|
+
}
|
|
910
|
+
// silent return if no password is provided and operation does not require a password
|
|
911
|
+
if (!password) {
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
const { backups } = await this.getWalletExternalServerKeyShareBackupInfo({
|
|
915
|
+
accountAddress
|
|
916
|
+
});
|
|
917
|
+
const { dynamic: dynamicKeyShareIds = [] } = backups;
|
|
918
|
+
if (!dynamicKeyShareIds || dynamicKeyShareIds.length === 0) {
|
|
919
|
+
throw new Error('No dynamic key shares found');
|
|
920
|
+
}
|
|
921
|
+
try {
|
|
922
|
+
await this.recoverEncryptedBackupByWallet({
|
|
923
|
+
accountAddress,
|
|
924
|
+
password,
|
|
925
|
+
walletOperation,
|
|
926
|
+
shareCount: 1,
|
|
927
|
+
storeRecoveredShares: false
|
|
928
|
+
});
|
|
929
|
+
} catch (error) {
|
|
930
|
+
this.logger.error('Error in verifying password', error);
|
|
931
|
+
throw new Error('Incorrect password');
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
async isPasswordEncrypted({ accountAddress }) {
|
|
935
|
+
const externalServerKeySharesBackupInfo = await this.getWalletExternalServerKeyShareBackupInfo({
|
|
936
|
+
accountAddress
|
|
937
|
+
});
|
|
938
|
+
return externalServerKeySharesBackupInfo == null ? void 0 : externalServerKeySharesBackupInfo.passwordEncrypted;
|
|
939
|
+
}
|
|
940
|
+
/**
|
|
941
|
+
* check if the operation requires a password
|
|
942
|
+
*/ async requiresPasswordForOperation({ accountAddress, walletOperation = core.WalletOperation.REACH_THRESHOLD }) {
|
|
943
|
+
const isEncrypted = await this.isPasswordEncrypted({
|
|
944
|
+
accountAddress
|
|
945
|
+
});
|
|
946
|
+
if (!isEncrypted) {
|
|
947
|
+
return false;
|
|
948
|
+
}
|
|
949
|
+
return this.requiresRestoreBackupSharesForOperation({
|
|
950
|
+
accountAddress,
|
|
951
|
+
walletOperation
|
|
952
|
+
});
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* check if the operation requires restoring backup shares
|
|
956
|
+
*/ async requiresRestoreBackupSharesForOperation({ accountAddress, walletOperation = core.WalletOperation.REACH_THRESHOLD }) {
|
|
957
|
+
const externalServerKeySharesBackupInfo = await this.getWalletExternalServerKeyShareBackupInfo({
|
|
958
|
+
accountAddress
|
|
959
|
+
});
|
|
960
|
+
const externalServerKeyShares = this.walletMap[accountAddress].externalServerKeyShares || [];
|
|
961
|
+
if (walletOperation === core.WalletOperation.REACH_ALL_PARTIES || walletOperation === core.WalletOperation.REFRESH || walletOperation === core.WalletOperation.RESHARE) {
|
|
962
|
+
return true;
|
|
963
|
+
}
|
|
964
|
+
const { requiredShareCount } = this.recoverStrategy({
|
|
965
|
+
externalServerKeySharesBackupInfo,
|
|
966
|
+
thresholdSignatureScheme: this.walletMap[accountAddress].thresholdSignatureScheme,
|
|
967
|
+
walletOperation
|
|
968
|
+
});
|
|
969
|
+
if (externalServerKeyShares.length >= requiredShareCount) {
|
|
970
|
+
return false;
|
|
971
|
+
}
|
|
972
|
+
return true;
|
|
973
|
+
}
|
|
974
|
+
async getWalletExternalServerKeyShareBackupInfo({ accountAddress }) {
|
|
975
|
+
var _this_walletMap_accountAddress_externalServerKeySharesBackupInfo_backups_BackupLocation_DYNAMIC, _this_walletMap_accountAddress_externalServerKeySharesBackupInfo_backups, _this_walletMap_accountAddress_externalServerKeySharesBackupInfo, _this_walletMap_accountAddress, _user_verifiedCredentials;
|
|
976
|
+
this.ensureApiClientAuthenticated();
|
|
977
|
+
// Return existing backup info if it exists
|
|
978
|
+
if (((_this_walletMap_accountAddress = this.walletMap[accountAddress]) == null ? void 0 : (_this_walletMap_accountAddress_externalServerKeySharesBackupInfo = _this_walletMap_accountAddress.externalServerKeySharesBackupInfo) == null ? void 0 : (_this_walletMap_accountAddress_externalServerKeySharesBackupInfo_backups = _this_walletMap_accountAddress_externalServerKeySharesBackupInfo.backups) == null ? void 0 : (_this_walletMap_accountAddress_externalServerKeySharesBackupInfo_backups_BackupLocation_DYNAMIC = _this_walletMap_accountAddress_externalServerKeySharesBackupInfo_backups[core.BackupLocation.DYNAMIC]) == null ? void 0 : _this_walletMap_accountAddress_externalServerKeySharesBackupInfo_backups_BackupLocation_DYNAMIC.length) > 0) {
|
|
979
|
+
return this.walletMap[accountAddress].externalServerKeySharesBackupInfo;
|
|
980
|
+
}
|
|
981
|
+
// Get backup info from server
|
|
982
|
+
const user = await this.apiClient.getUser();
|
|
983
|
+
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
984
|
+
return getExternalServerKeyShareBackupInfo({
|
|
985
|
+
walletProperties: wallet == null ? void 0 : wallet.walletProperties
|
|
986
|
+
});
|
|
987
|
+
}
|
|
988
|
+
async getWallet({ accountAddress, walletOperation = core.WalletOperation.NO_OPERATION, shareCount = undefined, password = undefined }) {
|
|
989
|
+
var _user_verifiedCredentials;
|
|
990
|
+
this.ensureApiClientAuthenticated();
|
|
991
|
+
const existingWalletCheck = await this.checkWalletFields({
|
|
992
|
+
accountAddress,
|
|
993
|
+
walletOperation,
|
|
994
|
+
shareCount
|
|
995
|
+
});
|
|
996
|
+
if (existingWalletCheck) {
|
|
997
|
+
this.logger.debug(`Wallet ${accountAddress} already exists`);
|
|
998
|
+
return this.walletMap[accountAddress];
|
|
999
|
+
}
|
|
1000
|
+
//todo: Question - why don't we just call getWallets here? so then all are preloaded
|
|
1001
|
+
// Fetch and restore wallet from server
|
|
1002
|
+
const user = await this.apiClient.getUser();
|
|
1003
|
+
const wallet = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.find((vc)=>vc.address.toLowerCase() === accountAddress.toLowerCase());
|
|
1004
|
+
this.logger.debug('Restoring wallet', wallet);
|
|
1005
|
+
const walletProperties = wallet.walletProperties;
|
|
1006
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress], {
|
|
1007
|
+
walletId: wallet.id,
|
|
1008
|
+
chainName: wallet.chainName,
|
|
1009
|
+
accountAddress,
|
|
1010
|
+
thresholdSignatureScheme: walletProperties.thresholdSignatureScheme,
|
|
1011
|
+
derivationPath: walletProperties.derivationPath,
|
|
1012
|
+
externalServerKeySharesBackupInfo: getExternalServerKeyShareBackupInfo({
|
|
1013
|
+
walletProperties
|
|
1014
|
+
})
|
|
1015
|
+
});
|
|
1016
|
+
if (walletOperation !== core.WalletOperation.NO_OPERATION && await this.requiresRestoreBackupSharesForOperation({
|
|
1017
|
+
accountAddress,
|
|
1018
|
+
walletOperation
|
|
1019
|
+
})) {
|
|
1020
|
+
const decryptedKeyShares = await this.recoverEncryptedBackupByWallet({
|
|
1021
|
+
accountAddress,
|
|
1022
|
+
password: password != null ? password : this.environmentId,
|
|
1023
|
+
walletOperation: walletOperation,
|
|
1024
|
+
shareCount
|
|
1025
|
+
});
|
|
1026
|
+
this.logger.debug('Recovered backup', decryptedKeyShares);
|
|
1027
|
+
}
|
|
1028
|
+
const walletCount = Object.keys(this.walletMap).length;
|
|
1029
|
+
if (walletCount === 0) {
|
|
1030
|
+
throw new Error('No wallets found');
|
|
1031
|
+
}
|
|
1032
|
+
// Return the only wallet if there's just one
|
|
1033
|
+
if (walletCount === 1) {
|
|
1034
|
+
return Object.values(this.walletMap)[0];
|
|
1035
|
+
}
|
|
1036
|
+
return this.walletMap[accountAddress];
|
|
1037
|
+
}
|
|
1038
|
+
async getWallets() {
|
|
1039
|
+
var _user_verifiedCredentials;
|
|
1040
|
+
this.ensureApiClientAuthenticated();
|
|
1041
|
+
const user = await this.apiClient.getUser();
|
|
1042
|
+
const waasWallets = (_user_verifiedCredentials = user.verifiedCredentials) == null ? void 0 : _user_verifiedCredentials.filter((vc)=>vc.walletName === 'dynamicwaas');
|
|
1043
|
+
const wallets = waasWallets.map((vc)=>{
|
|
1044
|
+
var _this_walletMap_vc_address, _this_walletMap_vc_address1, _vc_walletProperties;
|
|
1045
|
+
var _this_walletMap_vc_address_derivationPath;
|
|
1046
|
+
return {
|
|
1047
|
+
walletId: vc.id,
|
|
1048
|
+
chainName: vc.chain,
|
|
1049
|
+
accountAddress: vc.address,
|
|
1050
|
+
serverKeySharesBackupInfo: getExternalServerKeyShareBackupInfo({
|
|
1051
|
+
walletProperties: vc.walletProperties || {}
|
|
1052
|
+
}),
|
|
1053
|
+
externalServerKeyShares: ((_this_walletMap_vc_address = this.walletMap[vc.address]) == null ? void 0 : _this_walletMap_vc_address.externalServerKeyShares) || [],
|
|
1054
|
+
derivationPath: (_this_walletMap_vc_address_derivationPath = (_this_walletMap_vc_address1 = this.walletMap[vc.address]) == null ? void 0 : _this_walletMap_vc_address1.derivationPath) != null ? _this_walletMap_vc_address_derivationPath : undefined,
|
|
1055
|
+
thresholdSignatureScheme: (_vc_walletProperties = vc.walletProperties) == null ? void 0 : _vc_walletProperties.thresholdSignatureScheme
|
|
1056
|
+
};
|
|
1057
|
+
});
|
|
1058
|
+
this.walletMap = wallets.reduce((acc, wallet)=>{
|
|
1059
|
+
var _acc_accountAddress;
|
|
1060
|
+
const accountAddress = wallet.accountAddress;
|
|
1061
|
+
acc[wallet.accountAddress] = {
|
|
1062
|
+
walletId: wallet.walletId,
|
|
1063
|
+
chainName: wallet.chainName,
|
|
1064
|
+
accountAddress: wallet.accountAddress,
|
|
1065
|
+
externalServerKeyShares: wallet.externalServerKeyShares || [],
|
|
1066
|
+
externalServerKeySharesBackupInfo: wallet.externalServerKeySharesBackupInfo,
|
|
1067
|
+
derivationPath: ((_acc_accountAddress = acc[accountAddress]) == null ? void 0 : _acc_accountAddress.derivationPath) || undefined,
|
|
1068
|
+
thresholdSignatureScheme: wallet.thresholdSignatureScheme
|
|
1069
|
+
};
|
|
1070
|
+
return acc;
|
|
1071
|
+
}, {});
|
|
1072
|
+
return wallets;
|
|
1073
|
+
}
|
|
1074
|
+
constructor({ environmentId, baseApiUrl, baseMPCRelayApiUrl, debug }){
|
|
1075
|
+
this.logger = logger;
|
|
1076
|
+
this.walletMap = {} // todo: store in session storage
|
|
1077
|
+
;
|
|
1078
|
+
this.isApiClientAuthenticated = false;
|
|
1079
|
+
this.environmentId = environmentId;
|
|
1080
|
+
this.baseMPCRelayApiUrl = baseMPCRelayApiUrl;
|
|
1081
|
+
this.baseApiUrl = baseApiUrl;
|
|
1082
|
+
this.debug = Boolean(debug);
|
|
1083
|
+
this.logger.setLogLevel(this.debug ? 'DEBUG' : DEFAULT_LOG_LEVEL);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
Object.defineProperty(exports, "BIP340", {
|
|
1088
|
+
enumerable: true,
|
|
1089
|
+
get: function () { return node.BIP340; }
|
|
1090
|
+
});
|
|
1091
|
+
Object.defineProperty(exports, "BIP340InitKeygenResult", {
|
|
1092
|
+
enumerable: true,
|
|
1093
|
+
get: function () { return node.BIP340InitKeygenResult; }
|
|
1094
|
+
});
|
|
1095
|
+
Object.defineProperty(exports, "BIP340KeygenResult", {
|
|
1096
|
+
enumerable: true,
|
|
1097
|
+
get: function () { return node.BIP340KeygenResult; }
|
|
1098
|
+
});
|
|
1099
|
+
Object.defineProperty(exports, "Ecdsa", {
|
|
1100
|
+
enumerable: true,
|
|
1101
|
+
get: function () { return node.Ecdsa; }
|
|
1102
|
+
});
|
|
1103
|
+
Object.defineProperty(exports, "EcdsaInitKeygenResult", {
|
|
1104
|
+
enumerable: true,
|
|
1105
|
+
get: function () { return node.EcdsaInitKeygenResult; }
|
|
1106
|
+
});
|
|
1107
|
+
Object.defineProperty(exports, "EcdsaKeygenResult", {
|
|
1108
|
+
enumerable: true,
|
|
1109
|
+
get: function () { return node.EcdsaKeygenResult; }
|
|
1110
|
+
});
|
|
1111
|
+
Object.defineProperty(exports, "EcdsaPublicKey", {
|
|
1112
|
+
enumerable: true,
|
|
1113
|
+
get: function () { return node.EcdsaPublicKey; }
|
|
1114
|
+
});
|
|
1115
|
+
Object.defineProperty(exports, "EcdsaSignature", {
|
|
1116
|
+
enumerable: true,
|
|
1117
|
+
get: function () { return node.EcdsaSignature; }
|
|
1118
|
+
});
|
|
1119
|
+
Object.defineProperty(exports, "Ed25519", {
|
|
1120
|
+
enumerable: true,
|
|
1121
|
+
get: function () { return node.Ed25519; }
|
|
1122
|
+
});
|
|
1123
|
+
Object.defineProperty(exports, "Ed25519InitKeygenResult", {
|
|
1124
|
+
enumerable: true,
|
|
1125
|
+
get: function () { return node.Ed25519InitKeygenResult; }
|
|
1126
|
+
});
|
|
1127
|
+
Object.defineProperty(exports, "Ed25519KeygenResult", {
|
|
1128
|
+
enumerable: true,
|
|
1129
|
+
get: function () { return node.Ed25519KeygenResult; }
|
|
1130
|
+
});
|
|
1131
|
+
Object.defineProperty(exports, "MessageHash", {
|
|
1132
|
+
enumerable: true,
|
|
1133
|
+
get: function () { return node.MessageHash; }
|
|
1134
|
+
});
|
|
1135
|
+
exports.DynamicWalletClient = DynamicWalletClient;
|
|
1136
|
+
exports.base64ToBytes = base64ToBytes;
|
|
1137
|
+
exports.bytesToBase64 = bytesToBase64;
|
|
1138
|
+
exports.ensureBase64Padding = ensureBase64Padding;
|
|
1139
|
+
exports.getExternalServerKeyShareBackupInfo = getExternalServerKeyShareBackupInfo;
|
|
1140
|
+
exports.getMPCSignatureScheme = getMPCSignatureScheme;
|
|
1141
|
+
exports.getMPCSigner = getMPCSigner;
|
|
1142
|
+
exports.isHexString = isHexString;
|
|
1143
|
+
exports.mergeUniqueKeyShares = mergeUniqueKeyShares;
|
|
1144
|
+
exports.retryPromise = retryPromise;
|
|
1145
|
+
exports.stringToBytes = stringToBytes;
|
|
1146
|
+
Object.keys(core).forEach(function (k) {
|
|
1147
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
1148
|
+
enumerable: true,
|
|
1149
|
+
get: function () { return core[k]; }
|
|
1150
|
+
});
|
|
1151
|
+
});
|