@dynamic-labs-wallet/sui 0.0.0-beta.3 → 0.0.0-beta.308.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.js +232 -45
- package/index.esm.js +228 -41
- package/package.json +6 -4
- package/src/client/client.d.ts +66 -7
- package/src/client/client.d.ts.map +1 -1
- package/src/client/constants.d.ts +2 -0
- package/src/client/constants.d.ts.map +1 -1
package/index.cjs.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var browser = require('@dynamic-labs-wallet/browser');
|
|
4
|
-
var ed25519 = require('@mysten/sui/keypairs/ed25519');
|
|
5
4
|
var cryptography = require('@mysten/sui/cryptography');
|
|
5
|
+
var ed25519 = require('@mysten/sui/keypairs/ed25519');
|
|
6
6
|
var verify = require('@mysten/sui/verify');
|
|
7
|
+
var converter = require('bech32-converting');
|
|
7
8
|
var bcs = require('@mysten/sui/bcs');
|
|
8
9
|
var blake2b = require('@noble/hashes/blake2b');
|
|
9
10
|
|
|
@@ -18,11 +19,6 @@ function _extends() {
|
|
|
18
19
|
return _extends.apply(this, arguments);
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
const ERROR_KEYGEN_FAILED = 'Error with keygen';
|
|
22
|
-
const ERROR_CREATE_WALLET_ACCOUNT = 'Error creating sui wallet account';
|
|
23
|
-
const ERROR_VERIFY_MESSAGE_SIGNATURE = 'Error verifying message signature';
|
|
24
|
-
const ERROR_VERIFY_TRANSACTION_SIGNATURE = 'Error verifying transaction signature';
|
|
25
|
-
|
|
26
22
|
const formatMessage = (message, intentScope)=>{
|
|
27
23
|
if (intentScope === 'TransactionData') {
|
|
28
24
|
const txBytes = Uint8Array.from(Buffer.from(message, 'hex'));
|
|
@@ -41,8 +37,12 @@ const formatMessage = (message, intentScope)=>{
|
|
|
41
37
|
};
|
|
42
38
|
|
|
43
39
|
class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
44
|
-
async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError }) {
|
|
40
|
+
async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
|
|
45
41
|
try {
|
|
42
|
+
let ceremonyCeremonyCompleteResolver;
|
|
43
|
+
const ceremonyCompletePromise = new Promise((resolve)=>{
|
|
44
|
+
ceremonyCeremonyCompleteResolver = resolve;
|
|
45
|
+
});
|
|
46
46
|
// Generate key shares for given threshold signature scheme (TSS)
|
|
47
47
|
const { rawPublicKey, clientKeyShares } = await this.keyGen({
|
|
48
48
|
chainName: this.chainName,
|
|
@@ -57,36 +57,45 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
57
57
|
thresholdSignatureScheme,
|
|
58
58
|
clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
|
|
59
59
|
});
|
|
60
|
+
this.logger.debug('walletMap updated for wallet', {
|
|
61
|
+
context: {
|
|
62
|
+
accountAddress,
|
|
63
|
+
walletId,
|
|
64
|
+
walletMap: this.walletMap
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
ceremonyCeremonyCompleteResolver(undefined);
|
|
60
68
|
}
|
|
61
69
|
});
|
|
70
|
+
// Wait for the ceremony to complete before proceeding
|
|
71
|
+
await ceremonyCompletePromise;
|
|
62
72
|
if (!rawPublicKey || !clientKeyShares) {
|
|
63
|
-
throw new Error(ERROR_KEYGEN_FAILED);
|
|
73
|
+
throw new Error(browser.ERROR_KEYGEN_FAILED);
|
|
64
74
|
}
|
|
65
75
|
const { accountAddress, publicKeyHex } = this.deriveAccountAddress({
|
|
66
76
|
rawPublicKey: rawPublicKey
|
|
67
77
|
});
|
|
68
78
|
// Update client key shares in wallet map
|
|
69
79
|
// warning: this might result in race condition if `onCeremonyComplete` executes at the same time
|
|
70
|
-
// TODO: remove this once iframe handling for secret shares is implemented
|
|
71
80
|
await this.setClientKeySharesToLocalStorage({
|
|
72
81
|
accountAddress,
|
|
73
82
|
clientKeyShares,
|
|
74
83
|
overwriteOrMerge: 'overwrite'
|
|
75
84
|
});
|
|
76
|
-
|
|
77
|
-
void this.storeEncryptedBackupByWalletWithRetry({
|
|
85
|
+
await this.storeEncryptedBackupByWalletWithRetry({
|
|
78
86
|
accountAddress,
|
|
79
87
|
clientKeyShares,
|
|
80
|
-
password
|
|
88
|
+
password,
|
|
89
|
+
signedSessionId
|
|
81
90
|
});
|
|
82
91
|
return {
|
|
83
92
|
accountAddress,
|
|
84
|
-
rawPublicKey,
|
|
93
|
+
rawPublicKey: rawPublicKey,
|
|
85
94
|
publicKeyHex
|
|
86
95
|
};
|
|
87
96
|
} catch (error) {
|
|
88
|
-
this.logger.error(ERROR_CREATE_WALLET_ACCOUNT, error);
|
|
89
|
-
throw new Error(ERROR_CREATE_WALLET_ACCOUNT);
|
|
97
|
+
this.logger.error(browser.ERROR_CREATE_WALLET_ACCOUNT, error);
|
|
98
|
+
throw new Error(browser.ERROR_CREATE_WALLET_ACCOUNT);
|
|
90
99
|
}
|
|
91
100
|
}
|
|
92
101
|
async getRawPublicKeyFromClientKeyShares({ chainName, clientKeyShare }) {
|
|
@@ -102,22 +111,28 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
102
111
|
/**
|
|
103
112
|
* Format Ed25519 signature to string that satisfies Sui signature standard
|
|
104
113
|
*/ async formatSignature(signatureEd25519, accountAddress) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
114
|
+
try {
|
|
115
|
+
// get public key from keyshare
|
|
116
|
+
// TODO: handle this more gracefully from the client key shares if possible
|
|
117
|
+
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
118
|
+
accountAddress
|
|
119
|
+
});
|
|
120
|
+
const rawPublicKey = await this.getRawPublicKeyFromClientKeyShares({
|
|
121
|
+
chainName: this.chainName,
|
|
122
|
+
clientKeyShare: clientKeyShares[0]
|
|
123
|
+
});
|
|
124
|
+
const rawPublicKeyBytes = Uint8Array.from(Buffer.from(rawPublicKey, 'hex'));
|
|
125
|
+
const suiPublicKey = new ed25519.Ed25519PublicKey(rawPublicKeyBytes);
|
|
126
|
+
const serializedSignature = cryptography.toSerializedSignature({
|
|
127
|
+
signature: signatureEd25519,
|
|
128
|
+
signatureScheme: 'ED25519',
|
|
129
|
+
publicKey: suiPublicKey
|
|
130
|
+
});
|
|
131
|
+
return serializedSignature;
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this.logger.error('Error formatting signature:', error);
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
121
136
|
}
|
|
122
137
|
async verifyMessageSignature({ message, signature, accountAddress }) {
|
|
123
138
|
try {
|
|
@@ -125,7 +140,7 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
125
140
|
const verifiedPublicKey = await verify.verifyPersonalMessageSignature(messageBytes, signature);
|
|
126
141
|
const isVerified = verifiedPublicKey.toSuiAddress().toLowerCase() === accountAddress.toLowerCase();
|
|
127
142
|
if (!isVerified) {
|
|
128
|
-
throw new Error(ERROR_VERIFY_MESSAGE_SIGNATURE);
|
|
143
|
+
throw new Error(browser.ERROR_VERIFY_MESSAGE_SIGNATURE);
|
|
129
144
|
}
|
|
130
145
|
} catch (error) {
|
|
131
146
|
this.logger.error('Error verifying signature:', error);
|
|
@@ -138,16 +153,16 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
138
153
|
const verifiedPublicKey = await verify.verifyTransactionSignature(txBytes, signature);
|
|
139
154
|
const isVerified = verifiedPublicKey.toSuiAddress().toLowerCase() === senderAddress.toLowerCase();
|
|
140
155
|
if (!isVerified) {
|
|
141
|
-
throw new Error(ERROR_VERIFY_TRANSACTION_SIGNATURE);
|
|
156
|
+
throw new Error(browser.ERROR_VERIFY_TRANSACTION_SIGNATURE);
|
|
142
157
|
}
|
|
143
158
|
} catch (error) {
|
|
144
159
|
this.logger.error('Error verifying signature:', error);
|
|
145
160
|
throw error;
|
|
146
161
|
}
|
|
147
162
|
}
|
|
148
|
-
async signMessage({ message, accountAddress, password = undefined }) {
|
|
163
|
+
async signMessage({ message, accountAddress, password = undefined, signedSessionId, mfaToken, onError }) {
|
|
149
164
|
if (!accountAddress) {
|
|
150
|
-
throw new Error(
|
|
165
|
+
throw new Error(browser.ERROR_ACCOUNT_ADDRESS_REQUIRED);
|
|
151
166
|
}
|
|
152
167
|
try {
|
|
153
168
|
const formattedMessage = formatMessage(message, 'PersonalMessage');
|
|
@@ -155,7 +170,13 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
155
170
|
message: formattedMessage,
|
|
156
171
|
accountAddress: accountAddress,
|
|
157
172
|
chainName: this.chainName,
|
|
158
|
-
password
|
|
173
|
+
password,
|
|
174
|
+
signedSessionId,
|
|
175
|
+
mfaToken,
|
|
176
|
+
context: {
|
|
177
|
+
suiMessage: message
|
|
178
|
+
},
|
|
179
|
+
onError
|
|
159
180
|
});
|
|
160
181
|
const formattedSignature = await this.formatSignature(signatureEd25519, accountAddress);
|
|
161
182
|
await this.verifyMessageSignature({
|
|
@@ -165,13 +186,13 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
165
186
|
});
|
|
166
187
|
return formattedSignature;
|
|
167
188
|
} catch (error) {
|
|
168
|
-
this.logger.error(
|
|
169
|
-
throw
|
|
189
|
+
this.logger.error(browser.ERROR_SIGN_MESSAGE, error);
|
|
190
|
+
throw new Error(browser.ERROR_SIGN_MESSAGE);
|
|
170
191
|
}
|
|
171
192
|
}
|
|
172
|
-
async signTransaction({ transaction, senderAddress, password = undefined }) {
|
|
193
|
+
async signTransaction({ transaction, senderAddress, password = undefined, signedSessionId, mfaToken, onError }) {
|
|
173
194
|
if (!senderAddress) {
|
|
174
|
-
throw new Error(
|
|
195
|
+
throw new Error(browser.ERROR_ACCOUNT_ADDRESS_REQUIRED);
|
|
175
196
|
}
|
|
176
197
|
try {
|
|
177
198
|
const formattedMessage = formatMessage(transaction, 'TransactionData');
|
|
@@ -179,7 +200,16 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
179
200
|
message: formattedMessage,
|
|
180
201
|
accountAddress: senderAddress,
|
|
181
202
|
chainName: this.chainName,
|
|
182
|
-
password
|
|
203
|
+
password,
|
|
204
|
+
signedSessionId,
|
|
205
|
+
mfaToken,
|
|
206
|
+
context: {
|
|
207
|
+
suiTransaction: {
|
|
208
|
+
chainId: '0x2',
|
|
209
|
+
serializedTransaction: transaction
|
|
210
|
+
}
|
|
211
|
+
},
|
|
212
|
+
onError
|
|
183
213
|
});
|
|
184
214
|
const formattedSignature = await this.formatSignature(signatureEd25519, senderAddress);
|
|
185
215
|
await this.verifyTransactionSignature({
|
|
@@ -194,26 +224,183 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
194
224
|
}
|
|
195
225
|
}
|
|
196
226
|
deriveAccountAddress({ rawPublicKey }) {
|
|
197
|
-
const
|
|
227
|
+
const pubKeyBytes = Buffer.from(rawPublicKey, 'hex');
|
|
228
|
+
const publicKey = new ed25519.Ed25519PublicKey(pubKeyBytes);
|
|
198
229
|
const accountAddress = publicKey.toSuiAddress();
|
|
199
230
|
return {
|
|
200
231
|
accountAddress,
|
|
201
|
-
publicKeyHex:
|
|
232
|
+
publicKeyHex: rawPublicKey
|
|
202
233
|
};
|
|
203
234
|
}
|
|
235
|
+
/**
|
|
236
|
+
* Converts a Sui private key from Bech32 format to a 64-character hex string.
|
|
237
|
+
* The output is compatible with RFC8032 Ed25519 private key format.
|
|
238
|
+
*
|
|
239
|
+
* @param suiPrivateKey - The Sui private key in Bech32 format starting with "suiprivkey1"
|
|
240
|
+
* @returns An object containing the private key and the private key bytes
|
|
241
|
+
* @throws Error if the input is not a valid Sui private key format
|
|
242
|
+
*/ convertSuiPrivateKey(suiPrivateKey) {
|
|
243
|
+
if (!suiPrivateKey.startsWith('suiprivkey1')) {
|
|
244
|
+
this.logger.debug('Sui private key not in Bech32 format');
|
|
245
|
+
return {
|
|
246
|
+
privateKey: suiPrivateKey,
|
|
247
|
+
privateKeyBytes: Buffer.from(suiPrivateKey, 'hex')
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
const suiConverter = converter('suiprivkey');
|
|
252
|
+
const hexKey = suiConverter.toHex(suiPrivateKey);
|
|
253
|
+
let cleanHex = hexKey.startsWith('0x00') ? hexKey.slice(4) : hexKey.startsWith('0x') ? hexKey.slice(2) : hexKey;
|
|
254
|
+
if (cleanHex.length > 64) {
|
|
255
|
+
cleanHex = cleanHex.slice(cleanHex.length - 64);
|
|
256
|
+
}
|
|
257
|
+
if (cleanHex.length !== 64) {
|
|
258
|
+
throw new Error(`Invalid output: Expected 64 characters, got ${cleanHex.length}`);
|
|
259
|
+
}
|
|
260
|
+
return {
|
|
261
|
+
privateKey: cleanHex.toLowerCase(),
|
|
262
|
+
privateKeyBytes: Buffer.from(cleanHex, 'hex')
|
|
263
|
+
};
|
|
264
|
+
} catch (error) {
|
|
265
|
+
if (error instanceof Error) {
|
|
266
|
+
throw new Error(`Failed to convert Sui private key: ${error.message}`);
|
|
267
|
+
}
|
|
268
|
+
throw new Error('Failed to convert Sui private key: Unknown error');
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Gets the public key for a given private key
|
|
273
|
+
* @param privateKeyBytes A Buffer containing the Ed25519 private key bytes
|
|
274
|
+
* @returns The public key (Sui address) derived from the private key
|
|
275
|
+
*/ getPublicKeyFromPrivateKey(privateKeyBytes) {
|
|
276
|
+
try {
|
|
277
|
+
const keypair = ed25519.Ed25519Keypair.fromSecretKey(privateKeyBytes);
|
|
278
|
+
const publicKey = keypair.getPublicKey();
|
|
279
|
+
const publicKeyBase58 = publicKey.toSuiAddress();
|
|
280
|
+
return publicKeyBase58;
|
|
281
|
+
} catch (error) {
|
|
282
|
+
this.logger.error('Unable to derive public key from private key. Check private key format', error instanceof Error ? error.message : 'Unknown error');
|
|
283
|
+
throw error;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Imports the private key for a given account address
|
|
288
|
+
*
|
|
289
|
+
* @param privateKey The private key to import, accepts both Bech32 and hex formats
|
|
290
|
+
* @param chainName The chain name to import the private key for
|
|
291
|
+
* @param thresholdSignatureScheme The threshold signature scheme to use
|
|
292
|
+
* @param password The password for encrypted backup shares
|
|
293
|
+
* @returns The account address, raw public key, and client key shares
|
|
294
|
+
*/ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
|
|
295
|
+
try {
|
|
296
|
+
let ceremonyCeremonyCompleteResolver;
|
|
297
|
+
const ceremonyCompletePromise = new Promise((resolve)=>{
|
|
298
|
+
ceremonyCeremonyCompleteResolver = resolve;
|
|
299
|
+
});
|
|
300
|
+
const { privateKey: formattedPrivateKey, privateKeyBytes } = await this.convertSuiPrivateKey(privateKey);
|
|
301
|
+
const publicKey = this.getPublicKeyFromPrivateKey(privateKeyBytes);
|
|
302
|
+
const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
|
|
303
|
+
chainName,
|
|
304
|
+
privateKey: formattedPrivateKey,
|
|
305
|
+
thresholdSignatureScheme,
|
|
306
|
+
onError: (error)=>{
|
|
307
|
+
this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
|
|
308
|
+
onError == null ? void 0 : onError(error);
|
|
309
|
+
},
|
|
310
|
+
onCeremonyComplete: (accountAddress, walletId)=>{
|
|
311
|
+
// update wallet map
|
|
312
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
|
|
313
|
+
accountAddress,
|
|
314
|
+
walletId,
|
|
315
|
+
chainName: this.chainName,
|
|
316
|
+
thresholdSignatureScheme,
|
|
317
|
+
clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
|
|
318
|
+
});
|
|
319
|
+
this.logger.debug('walletMap updated for wallet', {
|
|
320
|
+
context: {
|
|
321
|
+
accountAddress,
|
|
322
|
+
walletId,
|
|
323
|
+
walletMap: this.walletMap
|
|
324
|
+
}
|
|
325
|
+
});
|
|
326
|
+
ceremonyCeremonyCompleteResolver(undefined);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
// Wait for the ceremony to complete before proceeding
|
|
330
|
+
await ceremonyCompletePromise;
|
|
331
|
+
if (!rawPublicKey || !clientKeyShares) {
|
|
332
|
+
throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
|
|
333
|
+
}
|
|
334
|
+
const { accountAddress } = await this.deriveAccountAddress({
|
|
335
|
+
rawPublicKey: rawPublicKey
|
|
336
|
+
});
|
|
337
|
+
if (accountAddress !== publicKey) {
|
|
338
|
+
throw new Error(`Public key mismatch: derived address ${accountAddress} !== public key ${publicKey}`);
|
|
339
|
+
}
|
|
340
|
+
// Update client key shares in wallet map
|
|
341
|
+
// warning: this might result in race condition if `onCeremonyComplete` executes at the same time
|
|
342
|
+
await this.setClientKeySharesToLocalStorage({
|
|
343
|
+
accountAddress,
|
|
344
|
+
clientKeyShares,
|
|
345
|
+
overwriteOrMerge: 'overwrite'
|
|
346
|
+
});
|
|
347
|
+
await this.storeEncryptedBackupByWalletWithRetry({
|
|
348
|
+
accountAddress,
|
|
349
|
+
clientKeyShares,
|
|
350
|
+
password,
|
|
351
|
+
signedSessionId
|
|
352
|
+
});
|
|
353
|
+
return {
|
|
354
|
+
accountAddress,
|
|
355
|
+
rawPublicKey: rawPublicKey,
|
|
356
|
+
clientKeyShares
|
|
357
|
+
};
|
|
358
|
+
} catch (error) {
|
|
359
|
+
this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
|
|
360
|
+
throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Exports the private key for a given account address
|
|
365
|
+
*
|
|
366
|
+
* @param accountAddress The account address to export the private key for
|
|
367
|
+
* @param password The password for encrypted backup shares
|
|
368
|
+
* @returns The private key in hex format
|
|
369
|
+
*/ async exportPrivateKey({ accountAddress, password = undefined, signedSessionId, mfaToken }) {
|
|
370
|
+
try {
|
|
371
|
+
const { derivedPrivateKey } = await this.exportKey({
|
|
372
|
+
accountAddress,
|
|
373
|
+
chainName: this.chainName,
|
|
374
|
+
password,
|
|
375
|
+
signedSessionId,
|
|
376
|
+
mfaToken
|
|
377
|
+
});
|
|
378
|
+
if (!derivedPrivateKey) {
|
|
379
|
+
throw new Error('Derived private key is undefined');
|
|
380
|
+
}
|
|
381
|
+
const privateScalarHex = derivedPrivateKey.slice(0, 64);
|
|
382
|
+
return privateScalarHex;
|
|
383
|
+
} catch (error) {
|
|
384
|
+
this.logger.error(browser.ERROR_EXPORT_PRIVATE_KEY, error);
|
|
385
|
+
throw new Error(browser.ERROR_EXPORT_PRIVATE_KEY);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
204
388
|
async getSuiWallets() {
|
|
205
389
|
const wallets = await this.getWallets();
|
|
206
390
|
const suiWallets = wallets.filter((wallet)=>wallet.chainName === 'sui');
|
|
207
391
|
return suiWallets;
|
|
208
392
|
}
|
|
209
|
-
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug }){
|
|
393
|
+
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, featureFlags, authMode = browser.AuthMode.HEADER, sdkVersion }){
|
|
210
394
|
super({
|
|
211
395
|
environmentId,
|
|
212
396
|
authToken,
|
|
213
397
|
baseApiUrl,
|
|
214
398
|
baseMPCRelayApiUrl,
|
|
215
399
|
storageKey,
|
|
216
|
-
debug
|
|
400
|
+
debug,
|
|
401
|
+
featureFlags,
|
|
402
|
+
authMode,
|
|
403
|
+
sdkVersion
|
|
217
404
|
}), this.chainName = 'SUI';
|
|
218
405
|
}
|
|
219
406
|
}
|
package/index.esm.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { DynamicWalletClient, getClientKeyShareBackupInfo, getMPCChainConfig } from '@dynamic-labs-wallet/browser';
|
|
2
|
-
import { Ed25519PublicKey } from '@mysten/sui/keypairs/ed25519';
|
|
1
|
+
import { DynamicWalletClient, getClientKeyShareBackupInfo, ERROR_KEYGEN_FAILED, ERROR_CREATE_WALLET_ACCOUNT, getMPCChainConfig, ERROR_VERIFY_MESSAGE_SIGNATURE, ERROR_VERIFY_TRANSACTION_SIGNATURE, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_SIGN_MESSAGE, ERROR_IMPORT_PRIVATE_KEY, ERROR_EXPORT_PRIVATE_KEY, AuthMode } from '@dynamic-labs-wallet/browser';
|
|
3
2
|
import { messageWithIntent, toSerializedSignature } from '@mysten/sui/cryptography';
|
|
3
|
+
import { Ed25519PublicKey, Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
|
|
4
4
|
import { verifyPersonalMessageSignature, verifyTransactionSignature } from '@mysten/sui/verify';
|
|
5
|
+
import converter from 'bech32-converting';
|
|
5
6
|
import { bcs } from '@mysten/sui/bcs';
|
|
6
7
|
import { blake2b } from '@noble/hashes/blake2b';
|
|
7
8
|
|
|
@@ -16,11 +17,6 @@ function _extends() {
|
|
|
16
17
|
return _extends.apply(this, arguments);
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
const ERROR_KEYGEN_FAILED = 'Error with keygen';
|
|
20
|
-
const ERROR_CREATE_WALLET_ACCOUNT = 'Error creating sui wallet account';
|
|
21
|
-
const ERROR_VERIFY_MESSAGE_SIGNATURE = 'Error verifying message signature';
|
|
22
|
-
const ERROR_VERIFY_TRANSACTION_SIGNATURE = 'Error verifying transaction signature';
|
|
23
|
-
|
|
24
20
|
const formatMessage = (message, intentScope)=>{
|
|
25
21
|
if (intentScope === 'TransactionData') {
|
|
26
22
|
const txBytes = Uint8Array.from(Buffer.from(message, 'hex'));
|
|
@@ -39,8 +35,12 @@ const formatMessage = (message, intentScope)=>{
|
|
|
39
35
|
};
|
|
40
36
|
|
|
41
37
|
class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
42
|
-
async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError }) {
|
|
38
|
+
async createWalletAccount({ thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
|
|
43
39
|
try {
|
|
40
|
+
let ceremonyCeremonyCompleteResolver;
|
|
41
|
+
const ceremonyCompletePromise = new Promise((resolve)=>{
|
|
42
|
+
ceremonyCeremonyCompleteResolver = resolve;
|
|
43
|
+
});
|
|
44
44
|
// Generate key shares for given threshold signature scheme (TSS)
|
|
45
45
|
const { rawPublicKey, clientKeyShares } = await this.keyGen({
|
|
46
46
|
chainName: this.chainName,
|
|
@@ -55,8 +55,18 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
55
55
|
thresholdSignatureScheme,
|
|
56
56
|
clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
|
|
57
57
|
});
|
|
58
|
+
this.logger.debug('walletMap updated for wallet', {
|
|
59
|
+
context: {
|
|
60
|
+
accountAddress,
|
|
61
|
+
walletId,
|
|
62
|
+
walletMap: this.walletMap
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
ceremonyCeremonyCompleteResolver(undefined);
|
|
58
66
|
}
|
|
59
67
|
});
|
|
68
|
+
// Wait for the ceremony to complete before proceeding
|
|
69
|
+
await ceremonyCompletePromise;
|
|
60
70
|
if (!rawPublicKey || !clientKeyShares) {
|
|
61
71
|
throw new Error(ERROR_KEYGEN_FAILED);
|
|
62
72
|
}
|
|
@@ -65,21 +75,20 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
65
75
|
});
|
|
66
76
|
// Update client key shares in wallet map
|
|
67
77
|
// warning: this might result in race condition if `onCeremonyComplete` executes at the same time
|
|
68
|
-
// TODO: remove this once iframe handling for secret shares is implemented
|
|
69
78
|
await this.setClientKeySharesToLocalStorage({
|
|
70
79
|
accountAddress,
|
|
71
80
|
clientKeyShares,
|
|
72
81
|
overwriteOrMerge: 'overwrite'
|
|
73
82
|
});
|
|
74
|
-
|
|
75
|
-
void this.storeEncryptedBackupByWalletWithRetry({
|
|
83
|
+
await this.storeEncryptedBackupByWalletWithRetry({
|
|
76
84
|
accountAddress,
|
|
77
85
|
clientKeyShares,
|
|
78
|
-
password
|
|
86
|
+
password,
|
|
87
|
+
signedSessionId
|
|
79
88
|
});
|
|
80
89
|
return {
|
|
81
90
|
accountAddress,
|
|
82
|
-
rawPublicKey,
|
|
91
|
+
rawPublicKey: rawPublicKey,
|
|
83
92
|
publicKeyHex
|
|
84
93
|
};
|
|
85
94
|
} catch (error) {
|
|
@@ -100,22 +109,28 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
100
109
|
/**
|
|
101
110
|
* Format Ed25519 signature to string that satisfies Sui signature standard
|
|
102
111
|
*/ async formatSignature(signatureEd25519, accountAddress) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
112
|
+
try {
|
|
113
|
+
// get public key from keyshare
|
|
114
|
+
// TODO: handle this more gracefully from the client key shares if possible
|
|
115
|
+
const clientKeyShares = await this.getClientKeySharesFromLocalStorage({
|
|
116
|
+
accountAddress
|
|
117
|
+
});
|
|
118
|
+
const rawPublicKey = await this.getRawPublicKeyFromClientKeyShares({
|
|
119
|
+
chainName: this.chainName,
|
|
120
|
+
clientKeyShare: clientKeyShares[0]
|
|
121
|
+
});
|
|
122
|
+
const rawPublicKeyBytes = Uint8Array.from(Buffer.from(rawPublicKey, 'hex'));
|
|
123
|
+
const suiPublicKey = new Ed25519PublicKey(rawPublicKeyBytes);
|
|
124
|
+
const serializedSignature = toSerializedSignature({
|
|
125
|
+
signature: signatureEd25519,
|
|
126
|
+
signatureScheme: 'ED25519',
|
|
127
|
+
publicKey: suiPublicKey
|
|
128
|
+
});
|
|
129
|
+
return serializedSignature;
|
|
130
|
+
} catch (error) {
|
|
131
|
+
this.logger.error('Error formatting signature:', error);
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
119
134
|
}
|
|
120
135
|
async verifyMessageSignature({ message, signature, accountAddress }) {
|
|
121
136
|
try {
|
|
@@ -143,9 +158,9 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
143
158
|
throw error;
|
|
144
159
|
}
|
|
145
160
|
}
|
|
146
|
-
async signMessage({ message, accountAddress, password = undefined }) {
|
|
161
|
+
async signMessage({ message, accountAddress, password = undefined, signedSessionId, mfaToken, onError }) {
|
|
147
162
|
if (!accountAddress) {
|
|
148
|
-
throw new Error(
|
|
163
|
+
throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
|
|
149
164
|
}
|
|
150
165
|
try {
|
|
151
166
|
const formattedMessage = formatMessage(message, 'PersonalMessage');
|
|
@@ -153,7 +168,13 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
153
168
|
message: formattedMessage,
|
|
154
169
|
accountAddress: accountAddress,
|
|
155
170
|
chainName: this.chainName,
|
|
156
|
-
password
|
|
171
|
+
password,
|
|
172
|
+
signedSessionId,
|
|
173
|
+
mfaToken,
|
|
174
|
+
context: {
|
|
175
|
+
suiMessage: message
|
|
176
|
+
},
|
|
177
|
+
onError
|
|
157
178
|
});
|
|
158
179
|
const formattedSignature = await this.formatSignature(signatureEd25519, accountAddress);
|
|
159
180
|
await this.verifyMessageSignature({
|
|
@@ -163,13 +184,13 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
163
184
|
});
|
|
164
185
|
return formattedSignature;
|
|
165
186
|
} catch (error) {
|
|
166
|
-
this.logger.error(
|
|
167
|
-
throw
|
|
187
|
+
this.logger.error(ERROR_SIGN_MESSAGE, error);
|
|
188
|
+
throw new Error(ERROR_SIGN_MESSAGE);
|
|
168
189
|
}
|
|
169
190
|
}
|
|
170
|
-
async signTransaction({ transaction, senderAddress, password = undefined }) {
|
|
191
|
+
async signTransaction({ transaction, senderAddress, password = undefined, signedSessionId, mfaToken, onError }) {
|
|
171
192
|
if (!senderAddress) {
|
|
172
|
-
throw new Error(
|
|
193
|
+
throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
|
|
173
194
|
}
|
|
174
195
|
try {
|
|
175
196
|
const formattedMessage = formatMessage(transaction, 'TransactionData');
|
|
@@ -177,7 +198,16 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
177
198
|
message: formattedMessage,
|
|
178
199
|
accountAddress: senderAddress,
|
|
179
200
|
chainName: this.chainName,
|
|
180
|
-
password
|
|
201
|
+
password,
|
|
202
|
+
signedSessionId,
|
|
203
|
+
mfaToken,
|
|
204
|
+
context: {
|
|
205
|
+
suiTransaction: {
|
|
206
|
+
chainId: '0x2',
|
|
207
|
+
serializedTransaction: transaction
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
onError
|
|
181
211
|
});
|
|
182
212
|
const formattedSignature = await this.formatSignature(signatureEd25519, senderAddress);
|
|
183
213
|
await this.verifyTransactionSignature({
|
|
@@ -192,26 +222,183 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
192
222
|
}
|
|
193
223
|
}
|
|
194
224
|
deriveAccountAddress({ rawPublicKey }) {
|
|
195
|
-
const
|
|
225
|
+
const pubKeyBytes = Buffer.from(rawPublicKey, 'hex');
|
|
226
|
+
const publicKey = new Ed25519PublicKey(pubKeyBytes);
|
|
196
227
|
const accountAddress = publicKey.toSuiAddress();
|
|
197
228
|
return {
|
|
198
229
|
accountAddress,
|
|
199
|
-
publicKeyHex:
|
|
230
|
+
publicKeyHex: rawPublicKey
|
|
200
231
|
};
|
|
201
232
|
}
|
|
233
|
+
/**
|
|
234
|
+
* Converts a Sui private key from Bech32 format to a 64-character hex string.
|
|
235
|
+
* The output is compatible with RFC8032 Ed25519 private key format.
|
|
236
|
+
*
|
|
237
|
+
* @param suiPrivateKey - The Sui private key in Bech32 format starting with "suiprivkey1"
|
|
238
|
+
* @returns An object containing the private key and the private key bytes
|
|
239
|
+
* @throws Error if the input is not a valid Sui private key format
|
|
240
|
+
*/ convertSuiPrivateKey(suiPrivateKey) {
|
|
241
|
+
if (!suiPrivateKey.startsWith('suiprivkey1')) {
|
|
242
|
+
this.logger.debug('Sui private key not in Bech32 format');
|
|
243
|
+
return {
|
|
244
|
+
privateKey: suiPrivateKey,
|
|
245
|
+
privateKeyBytes: Buffer.from(suiPrivateKey, 'hex')
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
const suiConverter = converter('suiprivkey');
|
|
250
|
+
const hexKey = suiConverter.toHex(suiPrivateKey);
|
|
251
|
+
let cleanHex = hexKey.startsWith('0x00') ? hexKey.slice(4) : hexKey.startsWith('0x') ? hexKey.slice(2) : hexKey;
|
|
252
|
+
if (cleanHex.length > 64) {
|
|
253
|
+
cleanHex = cleanHex.slice(cleanHex.length - 64);
|
|
254
|
+
}
|
|
255
|
+
if (cleanHex.length !== 64) {
|
|
256
|
+
throw new Error(`Invalid output: Expected 64 characters, got ${cleanHex.length}`);
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
privateKey: cleanHex.toLowerCase(),
|
|
260
|
+
privateKeyBytes: Buffer.from(cleanHex, 'hex')
|
|
261
|
+
};
|
|
262
|
+
} catch (error) {
|
|
263
|
+
if (error instanceof Error) {
|
|
264
|
+
throw new Error(`Failed to convert Sui private key: ${error.message}`);
|
|
265
|
+
}
|
|
266
|
+
throw new Error('Failed to convert Sui private key: Unknown error');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Gets the public key for a given private key
|
|
271
|
+
* @param privateKeyBytes A Buffer containing the Ed25519 private key bytes
|
|
272
|
+
* @returns The public key (Sui address) derived from the private key
|
|
273
|
+
*/ getPublicKeyFromPrivateKey(privateKeyBytes) {
|
|
274
|
+
try {
|
|
275
|
+
const keypair = Ed25519Keypair.fromSecretKey(privateKeyBytes);
|
|
276
|
+
const publicKey = keypair.getPublicKey();
|
|
277
|
+
const publicKeyBase58 = publicKey.toSuiAddress();
|
|
278
|
+
return publicKeyBase58;
|
|
279
|
+
} catch (error) {
|
|
280
|
+
this.logger.error('Unable to derive public key from private key. Check private key format', error instanceof Error ? error.message : 'Unknown error');
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Imports the private key for a given account address
|
|
286
|
+
*
|
|
287
|
+
* @param privateKey The private key to import, accepts both Bech32 and hex formats
|
|
288
|
+
* @param chainName The chain name to import the private key for
|
|
289
|
+
* @param thresholdSignatureScheme The threshold signature scheme to use
|
|
290
|
+
* @param password The password for encrypted backup shares
|
|
291
|
+
* @returns The account address, raw public key, and client key shares
|
|
292
|
+
*/ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
|
|
293
|
+
try {
|
|
294
|
+
let ceremonyCeremonyCompleteResolver;
|
|
295
|
+
const ceremonyCompletePromise = new Promise((resolve)=>{
|
|
296
|
+
ceremonyCeremonyCompleteResolver = resolve;
|
|
297
|
+
});
|
|
298
|
+
const { privateKey: formattedPrivateKey, privateKeyBytes } = await this.convertSuiPrivateKey(privateKey);
|
|
299
|
+
const publicKey = this.getPublicKeyFromPrivateKey(privateKeyBytes);
|
|
300
|
+
const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
|
|
301
|
+
chainName,
|
|
302
|
+
privateKey: formattedPrivateKey,
|
|
303
|
+
thresholdSignatureScheme,
|
|
304
|
+
onError: (error)=>{
|
|
305
|
+
this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
|
|
306
|
+
onError == null ? void 0 : onError(error);
|
|
307
|
+
},
|
|
308
|
+
onCeremonyComplete: (accountAddress, walletId)=>{
|
|
309
|
+
// update wallet map
|
|
310
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
|
|
311
|
+
accountAddress,
|
|
312
|
+
walletId,
|
|
313
|
+
chainName: this.chainName,
|
|
314
|
+
thresholdSignatureScheme,
|
|
315
|
+
clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
|
|
316
|
+
});
|
|
317
|
+
this.logger.debug('walletMap updated for wallet', {
|
|
318
|
+
context: {
|
|
319
|
+
accountAddress,
|
|
320
|
+
walletId,
|
|
321
|
+
walletMap: this.walletMap
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
ceremonyCeremonyCompleteResolver(undefined);
|
|
325
|
+
}
|
|
326
|
+
});
|
|
327
|
+
// Wait for the ceremony to complete before proceeding
|
|
328
|
+
await ceremonyCompletePromise;
|
|
329
|
+
if (!rawPublicKey || !clientKeyShares) {
|
|
330
|
+
throw new Error(ERROR_IMPORT_PRIVATE_KEY);
|
|
331
|
+
}
|
|
332
|
+
const { accountAddress } = await this.deriveAccountAddress({
|
|
333
|
+
rawPublicKey: rawPublicKey
|
|
334
|
+
});
|
|
335
|
+
if (accountAddress !== publicKey) {
|
|
336
|
+
throw new Error(`Public key mismatch: derived address ${accountAddress} !== public key ${publicKey}`);
|
|
337
|
+
}
|
|
338
|
+
// Update client key shares in wallet map
|
|
339
|
+
// warning: this might result in race condition if `onCeremonyComplete` executes at the same time
|
|
340
|
+
await this.setClientKeySharesToLocalStorage({
|
|
341
|
+
accountAddress,
|
|
342
|
+
clientKeyShares,
|
|
343
|
+
overwriteOrMerge: 'overwrite'
|
|
344
|
+
});
|
|
345
|
+
await this.storeEncryptedBackupByWalletWithRetry({
|
|
346
|
+
accountAddress,
|
|
347
|
+
clientKeyShares,
|
|
348
|
+
password,
|
|
349
|
+
signedSessionId
|
|
350
|
+
});
|
|
351
|
+
return {
|
|
352
|
+
accountAddress,
|
|
353
|
+
rawPublicKey: rawPublicKey,
|
|
354
|
+
clientKeyShares
|
|
355
|
+
};
|
|
356
|
+
} catch (error) {
|
|
357
|
+
this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
|
|
358
|
+
throw new Error(ERROR_IMPORT_PRIVATE_KEY);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Exports the private key for a given account address
|
|
363
|
+
*
|
|
364
|
+
* @param accountAddress The account address to export the private key for
|
|
365
|
+
* @param password The password for encrypted backup shares
|
|
366
|
+
* @returns The private key in hex format
|
|
367
|
+
*/ async exportPrivateKey({ accountAddress, password = undefined, signedSessionId, mfaToken }) {
|
|
368
|
+
try {
|
|
369
|
+
const { derivedPrivateKey } = await this.exportKey({
|
|
370
|
+
accountAddress,
|
|
371
|
+
chainName: this.chainName,
|
|
372
|
+
password,
|
|
373
|
+
signedSessionId,
|
|
374
|
+
mfaToken
|
|
375
|
+
});
|
|
376
|
+
if (!derivedPrivateKey) {
|
|
377
|
+
throw new Error('Derived private key is undefined');
|
|
378
|
+
}
|
|
379
|
+
const privateScalarHex = derivedPrivateKey.slice(0, 64);
|
|
380
|
+
return privateScalarHex;
|
|
381
|
+
} catch (error) {
|
|
382
|
+
this.logger.error(ERROR_EXPORT_PRIVATE_KEY, error);
|
|
383
|
+
throw new Error(ERROR_EXPORT_PRIVATE_KEY);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
202
386
|
async getSuiWallets() {
|
|
203
387
|
const wallets = await this.getWallets();
|
|
204
388
|
const suiWallets = wallets.filter((wallet)=>wallet.chainName === 'sui');
|
|
205
389
|
return suiWallets;
|
|
206
390
|
}
|
|
207
|
-
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug }){
|
|
391
|
+
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, featureFlags, authMode = AuthMode.HEADER, sdkVersion }){
|
|
208
392
|
super({
|
|
209
393
|
environmentId,
|
|
210
394
|
authToken,
|
|
211
395
|
baseApiUrl,
|
|
212
396
|
baseMPCRelayApiUrl,
|
|
213
397
|
storageKey,
|
|
214
|
-
debug
|
|
398
|
+
debug,
|
|
399
|
+
featureFlags,
|
|
400
|
+
authMode,
|
|
401
|
+
sdkVersion
|
|
215
402
|
}), this.chainName = 'SUI';
|
|
216
403
|
}
|
|
217
404
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/sui",
|
|
3
|
-
"version": "0.0.0-beta.
|
|
3
|
+
"version": "0.0.0-beta.308.1",
|
|
4
4
|
"license": "MIT",
|
|
5
|
+
"type": "commonjs",
|
|
5
6
|
"dependencies": {
|
|
6
|
-
"@dynamic-labs-wallet/browser": "0.0.0-beta.
|
|
7
|
+
"@dynamic-labs-wallet/browser": "0.0.0-beta.308.1",
|
|
7
8
|
"@mysten/sui": "1.26.0",
|
|
8
|
-
"@noble/hashes": "1.7.1"
|
|
9
|
+
"@noble/hashes": "1.7.1",
|
|
10
|
+
"bech32-converting": "^1.0.9"
|
|
9
11
|
},
|
|
10
12
|
"publishConfig": {
|
|
11
13
|
"access": "public"
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
"types": "./index.esm.d.ts",
|
|
28
30
|
"import": "./index.esm.js",
|
|
29
31
|
"require": "./index.cjs.js",
|
|
30
|
-
"default": "./index.
|
|
32
|
+
"default": "./index.esm.js"
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
}
|
package/src/client/client.d.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import { ClientKeyShare, DynamicWalletClient,
|
|
1
|
+
import { ClientKeyShare, DynamicWalletClient, DynamicWalletClientProps, ThresholdSignatureScheme } from '@dynamic-labs-wallet/browser';
|
|
2
2
|
export declare class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
3
3
|
readonly chainName = "SUI";
|
|
4
|
-
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, }: DynamicWalletClientProps);
|
|
5
|
-
createWalletAccount({ thresholdSignatureScheme, password, onError, }: {
|
|
4
|
+
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, featureFlags, authMode, sdkVersion, }: DynamicWalletClientProps);
|
|
5
|
+
createWalletAccount({ thresholdSignatureScheme, password, onError, signedSessionId, }: {
|
|
6
6
|
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
7
7
|
password?: string;
|
|
8
8
|
onError?: (error: Error) => void;
|
|
9
|
+
signedSessionId: string;
|
|
9
10
|
}): Promise<{
|
|
10
11
|
accountAddress: string;
|
|
11
12
|
publicKeyHex: string;
|
|
12
|
-
rawPublicKey:
|
|
13
|
+
rawPublicKey: string | undefined;
|
|
13
14
|
}>;
|
|
14
15
|
getRawPublicKeyFromClientKeyShares({ chainName, clientKeyShare, }: {
|
|
15
16
|
chainName: string;
|
|
@@ -21,22 +22,80 @@ export declare class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
21
22
|
private formatSignature;
|
|
22
23
|
private verifyMessageSignature;
|
|
23
24
|
private verifyTransactionSignature;
|
|
24
|
-
signMessage({ message, accountAddress, password, }: {
|
|
25
|
+
signMessage({ message, accountAddress, password, signedSessionId, mfaToken, onError, }: {
|
|
25
26
|
message: string;
|
|
26
27
|
accountAddress: string;
|
|
27
28
|
password?: string;
|
|
29
|
+
signedSessionId: string;
|
|
30
|
+
mfaToken?: string;
|
|
31
|
+
onError?: (error: Error) => void;
|
|
28
32
|
}): Promise<string>;
|
|
29
|
-
signTransaction({ transaction, senderAddress, password, }: {
|
|
33
|
+
signTransaction({ transaction, senderAddress, password, signedSessionId, mfaToken, onError, }: {
|
|
30
34
|
transaction: string;
|
|
31
35
|
senderAddress: string;
|
|
32
36
|
password?: string;
|
|
37
|
+
signedSessionId: string;
|
|
38
|
+
mfaToken?: string;
|
|
39
|
+
onError?: (error: Error) => void;
|
|
33
40
|
}): Promise<string>;
|
|
34
41
|
deriveAccountAddress({ rawPublicKey }: {
|
|
35
|
-
rawPublicKey:
|
|
42
|
+
rawPublicKey: string;
|
|
36
43
|
}): {
|
|
37
44
|
accountAddress: string;
|
|
38
45
|
publicKeyHex: string;
|
|
39
46
|
};
|
|
47
|
+
/**
|
|
48
|
+
* Converts a Sui private key from Bech32 format to a 64-character hex string.
|
|
49
|
+
* The output is compatible with RFC8032 Ed25519 private key format.
|
|
50
|
+
*
|
|
51
|
+
* @param suiPrivateKey - The Sui private key in Bech32 format starting with "suiprivkey1"
|
|
52
|
+
* @returns An object containing the private key and the private key bytes
|
|
53
|
+
* @throws Error if the input is not a valid Sui private key format
|
|
54
|
+
*/
|
|
55
|
+
convertSuiPrivateKey(suiPrivateKey: string): {
|
|
56
|
+
privateKey: string;
|
|
57
|
+
privateKeyBytes: Buffer;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Gets the public key for a given private key
|
|
61
|
+
* @param privateKeyBytes A Buffer containing the Ed25519 private key bytes
|
|
62
|
+
* @returns The public key (Sui address) derived from the private key
|
|
63
|
+
*/
|
|
64
|
+
getPublicKeyFromPrivateKey(privateKeyBytes: Buffer): string;
|
|
65
|
+
/**
|
|
66
|
+
* Imports the private key for a given account address
|
|
67
|
+
*
|
|
68
|
+
* @param privateKey The private key to import, accepts both Bech32 and hex formats
|
|
69
|
+
* @param chainName The chain name to import the private key for
|
|
70
|
+
* @param thresholdSignatureScheme The threshold signature scheme to use
|
|
71
|
+
* @param password The password for encrypted backup shares
|
|
72
|
+
* @returns The account address, raw public key, and client key shares
|
|
73
|
+
*/
|
|
74
|
+
importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, onError, signedSessionId, }: {
|
|
75
|
+
privateKey: string;
|
|
76
|
+
chainName: string;
|
|
77
|
+
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
78
|
+
password?: string;
|
|
79
|
+
onError?: (error: Error) => void;
|
|
80
|
+
signedSessionId: string;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
accountAddress: string;
|
|
83
|
+
rawPublicKey: string | undefined;
|
|
84
|
+
clientKeyShares: ClientKeyShare[];
|
|
85
|
+
}>;
|
|
86
|
+
/**
|
|
87
|
+
* Exports the private key for a given account address
|
|
88
|
+
*
|
|
89
|
+
* @param accountAddress The account address to export the private key for
|
|
90
|
+
* @param password The password for encrypted backup shares
|
|
91
|
+
* @returns The private key in hex format
|
|
92
|
+
*/
|
|
93
|
+
exportPrivateKey({ accountAddress, password, signedSessionId, mfaToken, }: {
|
|
94
|
+
accountAddress: string;
|
|
95
|
+
password?: string;
|
|
96
|
+
signedSessionId: string;
|
|
97
|
+
mfaToken?: string;
|
|
98
|
+
}): Promise<string>;
|
|
40
99
|
getSuiWallets(): Promise<any>;
|
|
41
100
|
}
|
|
42
101
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export declare const ERROR_KEYGEN_FAILED = "Error with keygen";
|
|
2
2
|
export declare const ERROR_CREATE_WALLET_ACCOUNT = "Error creating sui wallet account";
|
|
3
|
+
export declare const ERROR_IMPORT_PRIVATE_KEY = "Error importing private key";
|
|
4
|
+
export declare const ERROR_EXPORT_PRIVATE_KEY = "Error exporting private key";
|
|
3
5
|
export declare const ERROR_SIGN_MESSAGE = "Error signing message";
|
|
4
6
|
export declare const ERROR_ACCOUNT_ADDRESS_REQUIRED = "Account address is required";
|
|
5
7
|
export declare const ERROR_VERIFY_MESSAGE_SIGNATURE = "Error verifying message signature";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/client/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,eAAO,MAAM,2BAA2B,sCAAsC,CAAC;AAE/E,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D,eAAO,MAAM,8BAA8B,gCAAgC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,sCACN,CAAC;AAEtC,eAAO,MAAM,kCAAkC,0CACN,CAAC"}
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/client/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,sBAAsB,CAAC;AAEvD,eAAO,MAAM,2BAA2B,sCAAsC,CAAC;AAE/E,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AAEtE,eAAO,MAAM,wBAAwB,gCAAgC,CAAC;AAEtE,eAAO,MAAM,kBAAkB,0BAA0B,CAAC;AAE1D,eAAO,MAAM,8BAA8B,gCAAgC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,sCACN,CAAC;AAEtC,eAAO,MAAM,kCAAkC,0CACN,CAAC"}
|