@dynamic-labs-wallet/sui 0.0.0-beta.3 → 0.0.0-beta.304.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 +220 -44
- package/index.esm.js +217 -41
- package/package.json +6 -4
- package/src/client/client.d.ts +64 -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
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var browser = require('@dynamic-labs-wallet/browser');
|
|
4
4
|
var ed25519 = require('@mysten/sui/keypairs/ed25519');
|
|
5
5
|
var cryptography = require('@mysten/sui/cryptography');
|
|
6
|
+
var converter = require('bech32-converting');
|
|
6
7
|
var verify = require('@mysten/sui/verify');
|
|
7
8
|
var bcs = require('@mysten/sui/bcs');
|
|
8
9
|
var blake2b = require('@noble/hashes/blake2b');
|
|
@@ -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 }) {
|
|
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,9 @@ 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
|
|
159
176
|
});
|
|
160
177
|
const formattedSignature = await this.formatSignature(signatureEd25519, accountAddress);
|
|
161
178
|
await this.verifyMessageSignature({
|
|
@@ -165,13 +182,13 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
165
182
|
});
|
|
166
183
|
return formattedSignature;
|
|
167
184
|
} catch (error) {
|
|
168
|
-
this.logger.error(
|
|
169
|
-
throw
|
|
185
|
+
this.logger.error(browser.ERROR_SIGN_MESSAGE, error);
|
|
186
|
+
throw new Error(browser.ERROR_SIGN_MESSAGE);
|
|
170
187
|
}
|
|
171
188
|
}
|
|
172
|
-
async signTransaction({ transaction, senderAddress, password = undefined }) {
|
|
189
|
+
async signTransaction({ transaction, senderAddress, password = undefined, signedSessionId, mfaToken }) {
|
|
173
190
|
if (!senderAddress) {
|
|
174
|
-
throw new Error(
|
|
191
|
+
throw new Error(browser.ERROR_ACCOUNT_ADDRESS_REQUIRED);
|
|
175
192
|
}
|
|
176
193
|
try {
|
|
177
194
|
const formattedMessage = formatMessage(transaction, 'TransactionData');
|
|
@@ -179,7 +196,9 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
179
196
|
message: formattedMessage,
|
|
180
197
|
accountAddress: senderAddress,
|
|
181
198
|
chainName: this.chainName,
|
|
182
|
-
password
|
|
199
|
+
password,
|
|
200
|
+
signedSessionId,
|
|
201
|
+
mfaToken
|
|
183
202
|
});
|
|
184
203
|
const formattedSignature = await this.formatSignature(signatureEd25519, senderAddress);
|
|
185
204
|
await this.verifyTransactionSignature({
|
|
@@ -194,26 +213,183 @@ class DynamicSuiWalletClient extends browser.DynamicWalletClient {
|
|
|
194
213
|
}
|
|
195
214
|
}
|
|
196
215
|
deriveAccountAddress({ rawPublicKey }) {
|
|
197
|
-
const
|
|
216
|
+
const pubKeyBytes = Buffer.from(rawPublicKey, 'hex');
|
|
217
|
+
const publicKey = new ed25519.Ed25519PublicKey(pubKeyBytes);
|
|
198
218
|
const accountAddress = publicKey.toSuiAddress();
|
|
199
219
|
return {
|
|
200
220
|
accountAddress,
|
|
201
|
-
publicKeyHex:
|
|
221
|
+
publicKeyHex: rawPublicKey
|
|
202
222
|
};
|
|
203
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Converts a Sui private key from Bech32 format to a 64-character hex string.
|
|
226
|
+
* The output is compatible with RFC8032 Ed25519 private key format.
|
|
227
|
+
*
|
|
228
|
+
* @param suiPrivateKey - The Sui private key in Bech32 format starting with "suiprivkey1"
|
|
229
|
+
* @returns An object containing the private key and the private key bytes
|
|
230
|
+
* @throws Error if the input is not a valid Sui private key format
|
|
231
|
+
*/ convertSuiPrivateKey(suiPrivateKey) {
|
|
232
|
+
if (!suiPrivateKey.startsWith('suiprivkey1')) {
|
|
233
|
+
this.logger.debug('Sui private key not in Bech32 format');
|
|
234
|
+
return {
|
|
235
|
+
privateKey: suiPrivateKey,
|
|
236
|
+
privateKeyBytes: Buffer.from(suiPrivateKey, 'hex')
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
try {
|
|
240
|
+
const suiConverter = converter('suiprivkey');
|
|
241
|
+
const hexKey = suiConverter.toHex(suiPrivateKey);
|
|
242
|
+
let cleanHex = hexKey.startsWith('0x00') ? hexKey.slice(4) : hexKey.startsWith('0x') ? hexKey.slice(2) : hexKey;
|
|
243
|
+
if (cleanHex.length > 64) {
|
|
244
|
+
cleanHex = cleanHex.slice(cleanHex.length - 64);
|
|
245
|
+
}
|
|
246
|
+
if (cleanHex.length !== 64) {
|
|
247
|
+
throw new Error(`Invalid output: Expected 64 characters, got ${cleanHex.length}`);
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
privateKey: cleanHex.toLowerCase(),
|
|
251
|
+
privateKeyBytes: Buffer.from(cleanHex, 'hex')
|
|
252
|
+
};
|
|
253
|
+
} catch (error) {
|
|
254
|
+
if (error instanceof Error) {
|
|
255
|
+
throw new Error(`Failed to convert Sui private key: ${error.message}`);
|
|
256
|
+
}
|
|
257
|
+
throw new Error('Failed to convert Sui private key: Unknown error');
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Gets the public key for a given private key
|
|
262
|
+
* @param privateKeyBytes A Buffer containing the Ed25519 private key bytes
|
|
263
|
+
* @returns The public key (Sui address) derived from the private key
|
|
264
|
+
*/ getPublicKeyFromPrivateKey(privateKeyBytes) {
|
|
265
|
+
try {
|
|
266
|
+
const keypair = ed25519.Ed25519Keypair.fromSecretKey(privateKeyBytes);
|
|
267
|
+
const publicKey = keypair.getPublicKey();
|
|
268
|
+
const publicKeyBase58 = publicKey.toSuiAddress();
|
|
269
|
+
return publicKeyBase58;
|
|
270
|
+
} catch (error) {
|
|
271
|
+
this.logger.error('Unable to derive public key from private key. Check private key format', error instanceof Error ? error.message : 'Unknown error');
|
|
272
|
+
throw error;
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Imports the private key for a given account address
|
|
277
|
+
*
|
|
278
|
+
* @param privateKey The private key to import, accepts both Bech32 and hex formats
|
|
279
|
+
* @param chainName The chain name to import the private key for
|
|
280
|
+
* @param thresholdSignatureScheme The threshold signature scheme to use
|
|
281
|
+
* @param password The password for encrypted backup shares
|
|
282
|
+
* @returns The account address, raw public key, and client key shares
|
|
283
|
+
*/ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
|
|
284
|
+
try {
|
|
285
|
+
let ceremonyCeremonyCompleteResolver;
|
|
286
|
+
const ceremonyCompletePromise = new Promise((resolve)=>{
|
|
287
|
+
ceremonyCeremonyCompleteResolver = resolve;
|
|
288
|
+
});
|
|
289
|
+
const { privateKey: formattedPrivateKey, privateKeyBytes } = await this.convertSuiPrivateKey(privateKey);
|
|
290
|
+
const publicKey = this.getPublicKeyFromPrivateKey(privateKeyBytes);
|
|
291
|
+
const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
|
|
292
|
+
chainName,
|
|
293
|
+
privateKey: formattedPrivateKey,
|
|
294
|
+
thresholdSignatureScheme,
|
|
295
|
+
onError: (error)=>{
|
|
296
|
+
this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
|
|
297
|
+
onError == null ? void 0 : onError(error);
|
|
298
|
+
},
|
|
299
|
+
onCeremonyComplete: (accountAddress, walletId)=>{
|
|
300
|
+
// update wallet map
|
|
301
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
|
|
302
|
+
accountAddress,
|
|
303
|
+
walletId,
|
|
304
|
+
chainName: this.chainName,
|
|
305
|
+
thresholdSignatureScheme,
|
|
306
|
+
clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
|
|
307
|
+
});
|
|
308
|
+
this.logger.debug('walletMap updated for wallet', {
|
|
309
|
+
context: {
|
|
310
|
+
accountAddress,
|
|
311
|
+
walletId,
|
|
312
|
+
walletMap: this.walletMap
|
|
313
|
+
}
|
|
314
|
+
});
|
|
315
|
+
ceremonyCeremonyCompleteResolver(undefined);
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
// Wait for the ceremony to complete before proceeding
|
|
319
|
+
await ceremonyCompletePromise;
|
|
320
|
+
if (!rawPublicKey || !clientKeyShares) {
|
|
321
|
+
throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
|
|
322
|
+
}
|
|
323
|
+
const { accountAddress } = await this.deriveAccountAddress({
|
|
324
|
+
rawPublicKey: rawPublicKey
|
|
325
|
+
});
|
|
326
|
+
if (accountAddress !== publicKey) {
|
|
327
|
+
throw new Error(`Public key mismatch: derived address ${accountAddress} !== public key ${publicKey}`);
|
|
328
|
+
}
|
|
329
|
+
// Update client key shares in wallet map
|
|
330
|
+
// warning: this might result in race condition if `onCeremonyComplete` executes at the same time
|
|
331
|
+
await this.setClientKeySharesToLocalStorage({
|
|
332
|
+
accountAddress,
|
|
333
|
+
clientKeyShares,
|
|
334
|
+
overwriteOrMerge: 'overwrite'
|
|
335
|
+
});
|
|
336
|
+
await this.storeEncryptedBackupByWalletWithRetry({
|
|
337
|
+
accountAddress,
|
|
338
|
+
clientKeyShares,
|
|
339
|
+
password,
|
|
340
|
+
signedSessionId
|
|
341
|
+
});
|
|
342
|
+
return {
|
|
343
|
+
accountAddress,
|
|
344
|
+
rawPublicKey: rawPublicKey,
|
|
345
|
+
clientKeyShares
|
|
346
|
+
};
|
|
347
|
+
} catch (error) {
|
|
348
|
+
this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
|
|
349
|
+
throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Exports the private key for a given account address
|
|
354
|
+
*
|
|
355
|
+
* @param accountAddress The account address to export the private key for
|
|
356
|
+
* @param password The password for encrypted backup shares
|
|
357
|
+
* @returns The private key in hex format
|
|
358
|
+
*/ async exportPrivateKey({ accountAddress, password = undefined, signedSessionId, mfaToken }) {
|
|
359
|
+
try {
|
|
360
|
+
const { derivedPrivateKey } = await this.exportKey({
|
|
361
|
+
accountAddress,
|
|
362
|
+
chainName: this.chainName,
|
|
363
|
+
password,
|
|
364
|
+
signedSessionId,
|
|
365
|
+
mfaToken
|
|
366
|
+
});
|
|
367
|
+
if (!derivedPrivateKey) {
|
|
368
|
+
throw new Error('Derived private key is undefined');
|
|
369
|
+
}
|
|
370
|
+
const privateScalarHex = derivedPrivateKey.slice(0, 64);
|
|
371
|
+
return privateScalarHex;
|
|
372
|
+
} catch (error) {
|
|
373
|
+
this.logger.error(browser.ERROR_EXPORT_PRIVATE_KEY, error);
|
|
374
|
+
throw new Error(browser.ERROR_EXPORT_PRIVATE_KEY);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
204
377
|
async getSuiWallets() {
|
|
205
378
|
const wallets = await this.getWallets();
|
|
206
379
|
const suiWallets = wallets.filter((wallet)=>wallet.chainName === 'sui');
|
|
207
380
|
return suiWallets;
|
|
208
381
|
}
|
|
209
|
-
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug }){
|
|
382
|
+
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, featureFlags, authMode = browser.AuthMode.HEADER, sdkVersion }){
|
|
210
383
|
super({
|
|
211
384
|
environmentId,
|
|
212
385
|
authToken,
|
|
213
386
|
baseApiUrl,
|
|
214
387
|
baseMPCRelayApiUrl,
|
|
215
388
|
storageKey,
|
|
216
|
-
debug
|
|
389
|
+
debug,
|
|
390
|
+
featureFlags,
|
|
391
|
+
authMode,
|
|
392
|
+
sdkVersion
|
|
217
393
|
}), this.chainName = 'SUI';
|
|
218
394
|
}
|
|
219
395
|
}
|
package/index.esm.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
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';
|
|
2
|
+
import { Ed25519PublicKey, Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
|
|
3
3
|
import { messageWithIntent, toSerializedSignature } from '@mysten/sui/cryptography';
|
|
4
|
+
import converter from 'bech32-converting';
|
|
4
5
|
import { verifyPersonalMessageSignature, verifyTransactionSignature } from '@mysten/sui/verify';
|
|
5
6
|
import { bcs } from '@mysten/sui/bcs';
|
|
6
7
|
import { blake2b } from '@noble/hashes/blake2b';
|
|
@@ -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 }) {
|
|
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,9 @@ 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
|
|
157
174
|
});
|
|
158
175
|
const formattedSignature = await this.formatSignature(signatureEd25519, accountAddress);
|
|
159
176
|
await this.verifyMessageSignature({
|
|
@@ -163,13 +180,13 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
163
180
|
});
|
|
164
181
|
return formattedSignature;
|
|
165
182
|
} catch (error) {
|
|
166
|
-
this.logger.error(
|
|
167
|
-
throw
|
|
183
|
+
this.logger.error(ERROR_SIGN_MESSAGE, error);
|
|
184
|
+
throw new Error(ERROR_SIGN_MESSAGE);
|
|
168
185
|
}
|
|
169
186
|
}
|
|
170
|
-
async signTransaction({ transaction, senderAddress, password = undefined }) {
|
|
187
|
+
async signTransaction({ transaction, senderAddress, password = undefined, signedSessionId, mfaToken }) {
|
|
171
188
|
if (!senderAddress) {
|
|
172
|
-
throw new Error(
|
|
189
|
+
throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
|
|
173
190
|
}
|
|
174
191
|
try {
|
|
175
192
|
const formattedMessage = formatMessage(transaction, 'TransactionData');
|
|
@@ -177,7 +194,9 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
177
194
|
message: formattedMessage,
|
|
178
195
|
accountAddress: senderAddress,
|
|
179
196
|
chainName: this.chainName,
|
|
180
|
-
password
|
|
197
|
+
password,
|
|
198
|
+
signedSessionId,
|
|
199
|
+
mfaToken
|
|
181
200
|
});
|
|
182
201
|
const formattedSignature = await this.formatSignature(signatureEd25519, senderAddress);
|
|
183
202
|
await this.verifyTransactionSignature({
|
|
@@ -192,26 +211,183 @@ class DynamicSuiWalletClient extends DynamicWalletClient {
|
|
|
192
211
|
}
|
|
193
212
|
}
|
|
194
213
|
deriveAccountAddress({ rawPublicKey }) {
|
|
195
|
-
const
|
|
214
|
+
const pubKeyBytes = Buffer.from(rawPublicKey, 'hex');
|
|
215
|
+
const publicKey = new Ed25519PublicKey(pubKeyBytes);
|
|
196
216
|
const accountAddress = publicKey.toSuiAddress();
|
|
197
217
|
return {
|
|
198
218
|
accountAddress,
|
|
199
|
-
publicKeyHex:
|
|
219
|
+
publicKeyHex: rawPublicKey
|
|
200
220
|
};
|
|
201
221
|
}
|
|
222
|
+
/**
|
|
223
|
+
* Converts a Sui private key from Bech32 format to a 64-character hex string.
|
|
224
|
+
* The output is compatible with RFC8032 Ed25519 private key format.
|
|
225
|
+
*
|
|
226
|
+
* @param suiPrivateKey - The Sui private key in Bech32 format starting with "suiprivkey1"
|
|
227
|
+
* @returns An object containing the private key and the private key bytes
|
|
228
|
+
* @throws Error if the input is not a valid Sui private key format
|
|
229
|
+
*/ convertSuiPrivateKey(suiPrivateKey) {
|
|
230
|
+
if (!suiPrivateKey.startsWith('suiprivkey1')) {
|
|
231
|
+
this.logger.debug('Sui private key not in Bech32 format');
|
|
232
|
+
return {
|
|
233
|
+
privateKey: suiPrivateKey,
|
|
234
|
+
privateKeyBytes: Buffer.from(suiPrivateKey, 'hex')
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
const suiConverter = converter('suiprivkey');
|
|
239
|
+
const hexKey = suiConverter.toHex(suiPrivateKey);
|
|
240
|
+
let cleanHex = hexKey.startsWith('0x00') ? hexKey.slice(4) : hexKey.startsWith('0x') ? hexKey.slice(2) : hexKey;
|
|
241
|
+
if (cleanHex.length > 64) {
|
|
242
|
+
cleanHex = cleanHex.slice(cleanHex.length - 64);
|
|
243
|
+
}
|
|
244
|
+
if (cleanHex.length !== 64) {
|
|
245
|
+
throw new Error(`Invalid output: Expected 64 characters, got ${cleanHex.length}`);
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
privateKey: cleanHex.toLowerCase(),
|
|
249
|
+
privateKeyBytes: Buffer.from(cleanHex, 'hex')
|
|
250
|
+
};
|
|
251
|
+
} catch (error) {
|
|
252
|
+
if (error instanceof Error) {
|
|
253
|
+
throw new Error(`Failed to convert Sui private key: ${error.message}`);
|
|
254
|
+
}
|
|
255
|
+
throw new Error('Failed to convert Sui private key: Unknown error');
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Gets the public key for a given private key
|
|
260
|
+
* @param privateKeyBytes A Buffer containing the Ed25519 private key bytes
|
|
261
|
+
* @returns The public key (Sui address) derived from the private key
|
|
262
|
+
*/ getPublicKeyFromPrivateKey(privateKeyBytes) {
|
|
263
|
+
try {
|
|
264
|
+
const keypair = Ed25519Keypair.fromSecretKey(privateKeyBytes);
|
|
265
|
+
const publicKey = keypair.getPublicKey();
|
|
266
|
+
const publicKeyBase58 = publicKey.toSuiAddress();
|
|
267
|
+
return publicKeyBase58;
|
|
268
|
+
} catch (error) {
|
|
269
|
+
this.logger.error('Unable to derive public key from private key. Check private key format', error instanceof Error ? error.message : 'Unknown error');
|
|
270
|
+
throw error;
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Imports the private key for a given account address
|
|
275
|
+
*
|
|
276
|
+
* @param privateKey The private key to import, accepts both Bech32 and hex formats
|
|
277
|
+
* @param chainName The chain name to import the private key for
|
|
278
|
+
* @param thresholdSignatureScheme The threshold signature scheme to use
|
|
279
|
+
* @param password The password for encrypted backup shares
|
|
280
|
+
* @returns The account address, raw public key, and client key shares
|
|
281
|
+
*/ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
|
|
282
|
+
try {
|
|
283
|
+
let ceremonyCeremonyCompleteResolver;
|
|
284
|
+
const ceremonyCompletePromise = new Promise((resolve)=>{
|
|
285
|
+
ceremonyCeremonyCompleteResolver = resolve;
|
|
286
|
+
});
|
|
287
|
+
const { privateKey: formattedPrivateKey, privateKeyBytes } = await this.convertSuiPrivateKey(privateKey);
|
|
288
|
+
const publicKey = this.getPublicKeyFromPrivateKey(privateKeyBytes);
|
|
289
|
+
const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
|
|
290
|
+
chainName,
|
|
291
|
+
privateKey: formattedPrivateKey,
|
|
292
|
+
thresholdSignatureScheme,
|
|
293
|
+
onError: (error)=>{
|
|
294
|
+
this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
|
|
295
|
+
onError == null ? void 0 : onError(error);
|
|
296
|
+
},
|
|
297
|
+
onCeremonyComplete: (accountAddress, walletId)=>{
|
|
298
|
+
// update wallet map
|
|
299
|
+
this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
|
|
300
|
+
accountAddress,
|
|
301
|
+
walletId,
|
|
302
|
+
chainName: this.chainName,
|
|
303
|
+
thresholdSignatureScheme,
|
|
304
|
+
clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
|
|
305
|
+
});
|
|
306
|
+
this.logger.debug('walletMap updated for wallet', {
|
|
307
|
+
context: {
|
|
308
|
+
accountAddress,
|
|
309
|
+
walletId,
|
|
310
|
+
walletMap: this.walletMap
|
|
311
|
+
}
|
|
312
|
+
});
|
|
313
|
+
ceremonyCeremonyCompleteResolver(undefined);
|
|
314
|
+
}
|
|
315
|
+
});
|
|
316
|
+
// Wait for the ceremony to complete before proceeding
|
|
317
|
+
await ceremonyCompletePromise;
|
|
318
|
+
if (!rawPublicKey || !clientKeyShares) {
|
|
319
|
+
throw new Error(ERROR_IMPORT_PRIVATE_KEY);
|
|
320
|
+
}
|
|
321
|
+
const { accountAddress } = await this.deriveAccountAddress({
|
|
322
|
+
rawPublicKey: rawPublicKey
|
|
323
|
+
});
|
|
324
|
+
if (accountAddress !== publicKey) {
|
|
325
|
+
throw new Error(`Public key mismatch: derived address ${accountAddress} !== public key ${publicKey}`);
|
|
326
|
+
}
|
|
327
|
+
// Update client key shares in wallet map
|
|
328
|
+
// warning: this might result in race condition if `onCeremonyComplete` executes at the same time
|
|
329
|
+
await this.setClientKeySharesToLocalStorage({
|
|
330
|
+
accountAddress,
|
|
331
|
+
clientKeyShares,
|
|
332
|
+
overwriteOrMerge: 'overwrite'
|
|
333
|
+
});
|
|
334
|
+
await this.storeEncryptedBackupByWalletWithRetry({
|
|
335
|
+
accountAddress,
|
|
336
|
+
clientKeyShares,
|
|
337
|
+
password,
|
|
338
|
+
signedSessionId
|
|
339
|
+
});
|
|
340
|
+
return {
|
|
341
|
+
accountAddress,
|
|
342
|
+
rawPublicKey: rawPublicKey,
|
|
343
|
+
clientKeyShares
|
|
344
|
+
};
|
|
345
|
+
} catch (error) {
|
|
346
|
+
this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
|
|
347
|
+
throw new Error(ERROR_IMPORT_PRIVATE_KEY);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Exports the private key for a given account address
|
|
352
|
+
*
|
|
353
|
+
* @param accountAddress The account address to export the private key for
|
|
354
|
+
* @param password The password for encrypted backup shares
|
|
355
|
+
* @returns The private key in hex format
|
|
356
|
+
*/ async exportPrivateKey({ accountAddress, password = undefined, signedSessionId, mfaToken }) {
|
|
357
|
+
try {
|
|
358
|
+
const { derivedPrivateKey } = await this.exportKey({
|
|
359
|
+
accountAddress,
|
|
360
|
+
chainName: this.chainName,
|
|
361
|
+
password,
|
|
362
|
+
signedSessionId,
|
|
363
|
+
mfaToken
|
|
364
|
+
});
|
|
365
|
+
if (!derivedPrivateKey) {
|
|
366
|
+
throw new Error('Derived private key is undefined');
|
|
367
|
+
}
|
|
368
|
+
const privateScalarHex = derivedPrivateKey.slice(0, 64);
|
|
369
|
+
return privateScalarHex;
|
|
370
|
+
} catch (error) {
|
|
371
|
+
this.logger.error(ERROR_EXPORT_PRIVATE_KEY, error);
|
|
372
|
+
throw new Error(ERROR_EXPORT_PRIVATE_KEY);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
202
375
|
async getSuiWallets() {
|
|
203
376
|
const wallets = await this.getWallets();
|
|
204
377
|
const suiWallets = wallets.filter((wallet)=>wallet.chainName === 'sui');
|
|
205
378
|
return suiWallets;
|
|
206
379
|
}
|
|
207
|
-
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug }){
|
|
380
|
+
constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, featureFlags, authMode = AuthMode.HEADER, sdkVersion }){
|
|
208
381
|
super({
|
|
209
382
|
environmentId,
|
|
210
383
|
authToken,
|
|
211
384
|
baseApiUrl,
|
|
212
385
|
baseMPCRelayApiUrl,
|
|
213
386
|
storageKey,
|
|
214
|
-
debug
|
|
387
|
+
debug,
|
|
388
|
+
featureFlags,
|
|
389
|
+
authMode,
|
|
390
|
+
sdkVersion
|
|
215
391
|
}), this.chainName = 'SUI';
|
|
216
392
|
}
|
|
217
393
|
}
|
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.304.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.304.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, ThresholdSignatureScheme, DynamicWalletClientProps } 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,78 @@ 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, }: {
|
|
25
26
|
message: string;
|
|
26
27
|
accountAddress: string;
|
|
27
28
|
password?: string;
|
|
29
|
+
signedSessionId: string;
|
|
30
|
+
mfaToken?: string;
|
|
28
31
|
}): Promise<string>;
|
|
29
|
-
signTransaction({ transaction, senderAddress, password, }: {
|
|
32
|
+
signTransaction({ transaction, senderAddress, password, signedSessionId, mfaToken, }: {
|
|
30
33
|
transaction: string;
|
|
31
34
|
senderAddress: string;
|
|
32
35
|
password?: string;
|
|
36
|
+
signedSessionId: string;
|
|
37
|
+
mfaToken?: string;
|
|
33
38
|
}): Promise<string>;
|
|
34
39
|
deriveAccountAddress({ rawPublicKey }: {
|
|
35
|
-
rawPublicKey:
|
|
40
|
+
rawPublicKey: string;
|
|
36
41
|
}): {
|
|
37
42
|
accountAddress: string;
|
|
38
43
|
publicKeyHex: string;
|
|
39
44
|
};
|
|
45
|
+
/**
|
|
46
|
+
* Converts a Sui private key from Bech32 format to a 64-character hex string.
|
|
47
|
+
* The output is compatible with RFC8032 Ed25519 private key format.
|
|
48
|
+
*
|
|
49
|
+
* @param suiPrivateKey - The Sui private key in Bech32 format starting with "suiprivkey1"
|
|
50
|
+
* @returns An object containing the private key and the private key bytes
|
|
51
|
+
* @throws Error if the input is not a valid Sui private key format
|
|
52
|
+
*/
|
|
53
|
+
convertSuiPrivateKey(suiPrivateKey: string): {
|
|
54
|
+
privateKey: string;
|
|
55
|
+
privateKeyBytes: Buffer;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Gets the public key for a given private key
|
|
59
|
+
* @param privateKeyBytes A Buffer containing the Ed25519 private key bytes
|
|
60
|
+
* @returns The public key (Sui address) derived from the private key
|
|
61
|
+
*/
|
|
62
|
+
getPublicKeyFromPrivateKey(privateKeyBytes: Buffer): string;
|
|
63
|
+
/**
|
|
64
|
+
* Imports the private key for a given account address
|
|
65
|
+
*
|
|
66
|
+
* @param privateKey The private key to import, accepts both Bech32 and hex formats
|
|
67
|
+
* @param chainName The chain name to import the private key for
|
|
68
|
+
* @param thresholdSignatureScheme The threshold signature scheme to use
|
|
69
|
+
* @param password The password for encrypted backup shares
|
|
70
|
+
* @returns The account address, raw public key, and client key shares
|
|
71
|
+
*/
|
|
72
|
+
importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, onError, signedSessionId, }: {
|
|
73
|
+
privateKey: string;
|
|
74
|
+
chainName: string;
|
|
75
|
+
thresholdSignatureScheme: ThresholdSignatureScheme;
|
|
76
|
+
password?: string;
|
|
77
|
+
onError?: (error: Error) => void;
|
|
78
|
+
signedSessionId: string;
|
|
79
|
+
}): Promise<{
|
|
80
|
+
accountAddress: string;
|
|
81
|
+
rawPublicKey: string | undefined;
|
|
82
|
+
clientKeyShares: ClientKeyShare[];
|
|
83
|
+
}>;
|
|
84
|
+
/**
|
|
85
|
+
* Exports the private key for a given account address
|
|
86
|
+
*
|
|
87
|
+
* @param accountAddress The account address to export the private key for
|
|
88
|
+
* @param password The password for encrypted backup shares
|
|
89
|
+
* @returns The private key in hex format
|
|
90
|
+
*/
|
|
91
|
+
exportPrivateKey({ accountAddress, password, signedSessionId, mfaToken, }: {
|
|
92
|
+
accountAddress: string;
|
|
93
|
+
password?: string;
|
|
94
|
+
signedSessionId: string;
|
|
95
|
+
mfaToken?: string;
|
|
96
|
+
}): Promise<string>;
|
|
40
97
|
getSuiWallets(): Promise<any>;
|
|
41
98
|
}
|
|
42
99
|
//# sourceMappingURL=client.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client/client.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,
|
|
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"}
|