@dynamic-labs-wallet/svm 0.0.0-preview.160.0 → 0.0.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 CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var browser = require('@dynamic-labs-wallet/browser');
4
- var bs58 = require('bs58');
5
4
  var web3_js = require('@solana/web3.js');
5
+ var bs58 = require('bs58');
6
6
 
7
7
  function _extends() {
8
8
  _extends = Object.assign || function assign(target) {
@@ -15,21 +15,18 @@ function _extends() {
15
15
  return _extends.apply(this, arguments);
16
16
  }
17
17
 
18
- const addSignatureToTransaction = ({ transaction, signature, signerPublicKey })=>{
19
- transaction.addSignature(signerPublicKey, Buffer.from(signature));
20
- return transaction;
21
- };
22
-
23
- const ERROR_CREATE_WALLET_ACCOUNT = 'Error creating svm wallet account';
24
-
25
18
  class DynamicSvmWalletClient extends browser.DynamicWalletClient {
26
19
  /**
27
20
  * Creates a wallet account on the Solana chain
28
21
  *
29
22
  * @param thresholdSignatureScheme The threshold signature scheme to use
30
23
  * @returns The account address, public key hex, raw public key, and client key shares
31
- */ async createWalletAccount({ thresholdSignatureScheme, password = undefined }) {
24
+ */ async createWalletAccount({ thresholdSignatureScheme, password = undefined, signedSessionId }) {
32
25
  try {
26
+ let ceremonyCeremonyCompleteResolver;
27
+ const ceremonyCompletePromise = new Promise((resolve)=>{
28
+ ceremonyCeremonyCompleteResolver = resolve;
29
+ });
33
30
  const { rawPublicKey, clientKeyShares } = await this.keyGen({
34
31
  chainName: this.chainName,
35
32
  thresholdSignatureScheme,
@@ -42,42 +39,49 @@ class DynamicSvmWalletClient extends browser.DynamicWalletClient {
42
39
  thresholdSignatureScheme,
43
40
  clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
44
41
  });
42
+ this.logger.debug('walletMap updated for wallet', {
43
+ context: {
44
+ accountAddress,
45
+ walletId,
46
+ walletMap: this.walletMap
47
+ }
48
+ });
49
+ ceremonyCeremonyCompleteResolver(undefined);
45
50
  }
46
51
  });
47
- if (!rawPublicKey || !(rawPublicKey instanceof Uint8Array)) {
48
- throw new Error('Raw public key is not a Uint8Array');
52
+ // Wait for the ceremony to complete before proceeding
53
+ await ceremonyCompletePromise;
54
+ if (!rawPublicKey || !(rawPublicKey instanceof Uint8Array || typeof rawPublicKey === 'string')) {
55
+ throw new Error('Raw public key is not a Uint8Array or string' + typeof rawPublicKey);
49
56
  }
50
57
  if (!clientKeyShares) {
51
- throw new Error('Error creating wallet account');
58
+ throw new Error(browser.ERROR_KEYGEN_FAILED);
52
59
  }
53
60
  const { accountAddress } = await this.deriveAccountAddress(rawPublicKey);
54
61
  // Update client key shares in wallet map
55
- // warning: this might result in race condition if `onCeremonyComplete` executes at the same time
56
- // TODO: remove this once iframe handling for secret shares is implemented
57
62
  await this.setClientKeySharesToLocalStorage({
58
63
  accountAddress,
59
64
  clientKeyShares,
60
65
  overwriteOrMerge: 'overwrite'
61
66
  });
62
- // Backup the new wallet without waiting for the promise to resolve
63
- void this.storeEncryptedBackupByWalletWithRetry({
67
+ await this.storeEncryptedBackupByWalletWithRetry({
64
68
  accountAddress,
65
69
  clientKeyShares,
66
- password
70
+ password,
71
+ signedSessionId
67
72
  });
68
73
  return {
69
74
  accountAddress,
70
- rawPublicKey: rawPublicKey,
71
- clientKeyShares
75
+ rawPublicKey
72
76
  };
73
77
  } catch (error) {
74
- this.logger.error(ERROR_CREATE_WALLET_ACCOUNT, error);
75
- throw new Error(ERROR_CREATE_WALLET_ACCOUNT);
78
+ this.logger.error(browser.ERROR_CREATE_WALLET_ACCOUNT, error);
79
+ throw new Error(browser.ERROR_CREATE_WALLET_ACCOUNT);
76
80
  }
77
81
  }
78
- // Function to properly derive account address
79
82
  async deriveAccountAddress(rawPublicKey) {
80
- const accountAddress = bs58.encode(rawPublicKey);
83
+ const pubKeyBytes = typeof rawPublicKey === 'string' ? new Uint8Array(Buffer.from(rawPublicKey, 'hex')) : rawPublicKey;
84
+ const accountAddress = bs58.encode(pubKeyBytes);
81
85
  return {
82
86
  accountAddress
83
87
  };
@@ -88,62 +92,55 @@ class DynamicSvmWalletClient extends browser.DynamicWalletClient {
88
92
  * @param message The message to sign (Uint8Array)
89
93
  * @param accountAddress Solana address (base58 encoded)
90
94
  * @param password The password for encrypted backup shares
91
- */ async signMessage({ message, accountAddress, password = undefined }) {
95
+ */ async signMessage({ message, accountAddress, password = undefined, signedSessionId, mfaToken }) {
92
96
  await this.verifyPassword({
93
97
  accountAddress,
94
98
  password,
95
- walletOperation: browser.WalletOperation.SIGN_MESSAGE
99
+ walletOperation: browser.WalletOperation.SIGN_MESSAGE,
100
+ signedSessionId
96
101
  });
97
102
  if (!accountAddress) {
98
- throw new Error('Account address is required');
103
+ throw new Error(browser.ERROR_ACCOUNT_ADDRESS_REQUIRED);
99
104
  }
100
105
  try {
101
106
  const signatureEd25519 = await this.sign({
102
107
  message,
103
108
  accountAddress: accountAddress,
104
109
  chainName: this.chainName,
105
- password
110
+ password,
111
+ signedSessionId,
112
+ mfaToken
106
113
  });
107
114
  const base58Signature = bs58.encode(signatureEd25519);
108
115
  return base58Signature;
109
116
  } catch (error) {
110
- this.logger.error('Error signing message:', error);
111
- throw error;
117
+ this.logger.error(browser.ERROR_SIGN_MESSAGE, error);
118
+ throw new Error(browser.ERROR_SIGN_MESSAGE);
112
119
  }
113
120
  }
114
- async signTransaction({ senderAddress, transaction, password = undefined }) {
121
+ async signTransaction({ senderAddress, transaction, password = undefined, signedSessionId, mfaToken, chainId }) {
115
122
  await this.verifyPassword({
116
123
  accountAddress: senderAddress,
117
124
  password,
118
- walletOperation: browser.WalletOperation.SIGN_TRANSACTION
125
+ walletOperation: browser.WalletOperation.SIGN_TRANSACTION,
126
+ signedSessionId
119
127
  });
120
128
  try {
121
- let messageToSign;
122
- if (transaction instanceof web3_js.VersionedTransaction) {
123
- // For versioned transactions, we need to sign the message directly
124
- const messageBytes = transaction.message.serialize();
125
- messageToSign = Buffer.from(messageBytes).toString('hex');
126
- } else {
127
- // For legacy transactions, serialize the message
128
- const messageBytes = transaction.serializeMessage();
129
- messageToSign = Buffer.from(messageBytes).toString('hex');
130
- }
131
- const signatureEd25519 = await this.sign({
132
- message: messageToSign,
133
- accountAddress: senderAddress,
134
- chainName: this.chainName,
135
- password
129
+ const base58SerializedTransaction = this.prepareTransactionForSigning(transaction);
130
+ const signParams = this.buildSignParams({
131
+ transaction,
132
+ senderAddress,
133
+ password,
134
+ signedSessionId,
135
+ mfaToken,
136
+ chainId,
137
+ base58SerializedTransaction
136
138
  });
139
+ const signatureEd25519 = await this.sign(signParams);
137
140
  if (!signatureEd25519) {
138
141
  throw new Error('Signature is undefined');
139
142
  }
140
- const senderPublicKey = new web3_js.PublicKey(senderAddress);
141
- const signedTransaction = addSignatureToTransaction({
142
- transaction,
143
- signature: signatureEd25519,
144
- signerPublicKey: senderPublicKey
145
- });
146
- return signedTransaction;
143
+ return Buffer.from(signatureEd25519).toString('hex');
147
144
  } catch (error) {
148
145
  this.logger.error('Error in signTransaction:', error);
149
146
  if (error instanceof Error) {
@@ -152,32 +149,59 @@ class DynamicSvmWalletClient extends browser.DynamicWalletClient {
152
149
  throw error;
153
150
  }
154
151
  }
152
+ prepareTransactionForSigning(transaction) {
153
+ const transactionBytes = new Uint8Array(Buffer.from(transaction, 'hex'));
154
+ const deserializedTransaction = web3_js.VersionedMessage.deserialize(transactionBytes);
155
+ const versionedTransaction = new web3_js.VersionedTransaction(deserializedTransaction);
156
+ const serializedTransaction = versionedTransaction.serialize();
157
+ return bs58.encode(serializedTransaction);
158
+ }
159
+ buildSignParams({ transaction, senderAddress, password, signedSessionId, mfaToken, chainId, base58SerializedTransaction }) {
160
+ const signParams = {
161
+ message: transaction,
162
+ accountAddress: senderAddress,
163
+ chainName: this.chainName,
164
+ password,
165
+ signedSessionId,
166
+ mfaToken
167
+ };
168
+ if (chainId !== undefined) {
169
+ signParams.context = {
170
+ svmTransaction: {
171
+ chainId,
172
+ method: 'signAndSendTransaction',
173
+ serializedTransactions: [
174
+ base58SerializedTransaction
175
+ ]
176
+ }
177
+ };
178
+ }
179
+ return signParams;
180
+ }
155
181
  /**
156
182
  * Exports the private key for a given account address
157
183
  *
158
184
  * @param accountAddress The account address to export the private key for
159
185
  * @param password The password for encrypted backup shares
160
186
  * @returns The private key
161
- */ async exportPrivateKey({ accountAddress, displayContainer, password = undefined }) {
187
+ */ async exportPrivateKey({ accountAddress, password = undefined, signedSessionId, mfaToken }) {
162
188
  await this.verifyPassword({
163
189
  accountAddress,
164
190
  password,
165
- walletOperation: browser.WalletOperation.EXPORT_PRIVATE_KEY
191
+ walletOperation: browser.WalletOperation.EXPORT_PRIVATE_KEY,
192
+ signedSessionId
166
193
  });
167
194
  const { derivedPrivateKey } = await this.exportKey({
168
195
  accountAddress,
169
196
  chainName: this.chainName,
170
- password
197
+ password,
198
+ signedSessionId,
199
+ mfaToken
171
200
  });
172
201
  if (!derivedPrivateKey) {
173
202
  throw new Error('Derived private key is undefined');
174
203
  }
175
- const encodedPrivateKey = bs58.encode(Buffer.from(derivedPrivateKey));
176
- // Display the private key in the container via iframe
177
- const { iframeDisplay } = await this.initializeIframeDisplayForContainer({
178
- container: displayContainer
179
- });
180
- iframeDisplay.displayPrivateKey(encodedPrivateKey);
204
+ return derivedPrivateKey;
181
205
  }
182
206
  /**
183
207
  * Exports the private key for a given account address
@@ -221,65 +245,89 @@ class DynamicSvmWalletClient extends browser.DynamicWalletClient {
221
245
  * @param thresholdSignatureScheme The threshold signature scheme to use
222
246
  * @param password The password for encrypted backup shares
223
247
  * @returns The account address, raw public key, and client key shares
224
- */ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError }) {
225
- //get public key from private key
226
- const publicKey = this.getPublicKeyFromPrivateKey(privateKey);
227
- const formattedPrivateKey = await this.decodePrivateKeyForSolana(privateKey);
228
- const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
229
- chainName,
230
- privateKey: formattedPrivateKey,
231
- thresholdSignatureScheme,
232
- onError,
233
- onCeremonyComplete: (accountAddress, walletId)=>{
234
- // update wallet map
235
- this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
236
- accountAddress,
237
- walletId,
238
- chainName: this.chainName,
239
- thresholdSignatureScheme,
240
- clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
241
- });
248
+ */ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
249
+ try {
250
+ let ceremonyCeremonyCompleteResolver;
251
+ const ceremonyCompletePromise = new Promise((resolve)=>{
252
+ ceremonyCeremonyCompleteResolver = resolve;
253
+ });
254
+ //get public key from private key
255
+ const publicKey = this.getPublicKeyFromPrivateKey(privateKey);
256
+ const formattedPrivateKey = this.decodePrivateKeyForSolana(privateKey);
257
+ const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
258
+ chainName,
259
+ privateKey: formattedPrivateKey,
260
+ thresholdSignatureScheme,
261
+ onError: (error)=>{
262
+ this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
263
+ onError == null ? void 0 : onError(error);
264
+ },
265
+ onCeremonyComplete: (accountAddress, walletId)=>{
266
+ // update wallet map
267
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
268
+ accountAddress,
269
+ walletId,
270
+ chainName: this.chainName,
271
+ thresholdSignatureScheme,
272
+ clientKeySharesBackupInfo: browser.getClientKeyShareBackupInfo()
273
+ });
274
+ this.logger.debug('walletMap updated for wallet', {
275
+ context: {
276
+ accountAddress,
277
+ walletId,
278
+ walletMap: this.walletMap
279
+ }
280
+ });
281
+ ceremonyCeremonyCompleteResolver(undefined);
282
+ }
283
+ });
284
+ // Wait for the ceremony to complete before proceeding
285
+ await ceremonyCompletePromise;
286
+ if (!rawPublicKey || !clientKeyShares) {
287
+ throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
242
288
  }
243
- });
244
- if (!rawPublicKey || !clientKeyShares) {
245
- throw new Error('Error creating wallet account');
246
- }
247
- const { accountAddress } = await this.deriveAccountAddress(rawPublicKey);
248
- if (accountAddress !== publicKey) {
249
- throw new Error(`Public key mismatch: derived address ${accountAddress} !== public key ${publicKey}`);
289
+ const { accountAddress } = await this.deriveAccountAddress(rawPublicKey);
290
+ if (accountAddress !== publicKey) {
291
+ throw new Error(`Public key mismatch: derived address ${accountAddress} !== public key ${publicKey}`);
292
+ }
293
+ // Update client key shares in wallet map
294
+ await this.setClientKeySharesToLocalStorage({
295
+ accountAddress,
296
+ clientKeyShares,
297
+ overwriteOrMerge: 'overwrite'
298
+ });
299
+ await this.storeEncryptedBackupByWalletWithRetry({
300
+ accountAddress,
301
+ clientKeyShares,
302
+ password,
303
+ signedSessionId
304
+ });
305
+ return {
306
+ accountAddress,
307
+ rawPublicKey: rawPublicKey
308
+ };
309
+ } catch (error) {
310
+ this.logger.error(browser.ERROR_IMPORT_PRIVATE_KEY, error);
311
+ throw new Error(browser.ERROR_IMPORT_PRIVATE_KEY);
250
312
  }
251
- // Update client key shares in wallet map
252
- // warning: this might result in race condition if `onCeremonyComplete` executes at the same time
253
- // TODO: remove this once iframe handling for secret shares is implemented
254
- await this.setClientKeySharesToLocalStorage({
255
- accountAddress,
256
- clientKeyShares,
257
- overwriteOrMerge: 'overwrite'
258
- });
259
- // Backup the new wallet without waiting for the promise to resolve
260
- void this.storeEncryptedBackupByWalletWithRetry({
261
- accountAddress,
262
- clientKeyShares,
263
- password
264
- });
265
- return {
266
- accountAddress,
267
- rawPublicKey: rawPublicKey,
268
- clientKeyShares
269
- };
270
313
  }
271
314
  async getSvmWallets() {
272
315
  const wallets = await this.getWallets();
273
316
  const svmWallets = wallets.filter((wallet)=>wallet.chainName === 'solana');
274
317
  return svmWallets;
275
318
  }
276
- constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl }){
319
+ constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, featureFlags, authMode = browser.AuthMode.HEADER, sdkVersion }){
277
320
  super({
278
321
  environmentId,
279
322
  authToken,
280
323
  baseApiUrl,
281
- baseMPCRelayApiUrl
282
- }), this.chainName = 'SOL';
324
+ baseMPCRelayApiUrl,
325
+ storageKey,
326
+ debug,
327
+ featureFlags,
328
+ authMode,
329
+ sdkVersion
330
+ }), this.chainName = 'SVM';
283
331
  }
284
332
  }
285
333
 
package/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
- import { DynamicWalletClient, getClientKeyShareBackupInfo, WalletOperation } from '@dynamic-labs-wallet/browser';
1
+ import { DynamicWalletClient, getClientKeyShareBackupInfo, ERROR_KEYGEN_FAILED, ERROR_CREATE_WALLET_ACCOUNT, WalletOperation, ERROR_ACCOUNT_ADDRESS_REQUIRED, ERROR_SIGN_MESSAGE, ERROR_IMPORT_PRIVATE_KEY, AuthMode } from '@dynamic-labs-wallet/browser';
2
+ import { VersionedMessage, VersionedTransaction, Keypair } from '@solana/web3.js';
2
3
  import bs58 from 'bs58';
3
- import { VersionedTransaction, PublicKey, Keypair } from '@solana/web3.js';
4
4
 
5
5
  function _extends() {
6
6
  _extends = Object.assign || function assign(target) {
@@ -13,21 +13,18 @@ function _extends() {
13
13
  return _extends.apply(this, arguments);
14
14
  }
15
15
 
16
- const addSignatureToTransaction = ({ transaction, signature, signerPublicKey })=>{
17
- transaction.addSignature(signerPublicKey, Buffer.from(signature));
18
- return transaction;
19
- };
20
-
21
- const ERROR_CREATE_WALLET_ACCOUNT = 'Error creating svm wallet account';
22
-
23
16
  class DynamicSvmWalletClient extends DynamicWalletClient {
24
17
  /**
25
18
  * Creates a wallet account on the Solana chain
26
19
  *
27
20
  * @param thresholdSignatureScheme The threshold signature scheme to use
28
21
  * @returns The account address, public key hex, raw public key, and client key shares
29
- */ async createWalletAccount({ thresholdSignatureScheme, password = undefined }) {
22
+ */ async createWalletAccount({ thresholdSignatureScheme, password = undefined, signedSessionId }) {
30
23
  try {
24
+ let ceremonyCeremonyCompleteResolver;
25
+ const ceremonyCompletePromise = new Promise((resolve)=>{
26
+ ceremonyCeremonyCompleteResolver = resolve;
27
+ });
31
28
  const { rawPublicKey, clientKeyShares } = await this.keyGen({
32
29
  chainName: this.chainName,
33
30
  thresholdSignatureScheme,
@@ -40,42 +37,49 @@ class DynamicSvmWalletClient extends DynamicWalletClient {
40
37
  thresholdSignatureScheme,
41
38
  clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
42
39
  });
40
+ this.logger.debug('walletMap updated for wallet', {
41
+ context: {
42
+ accountAddress,
43
+ walletId,
44
+ walletMap: this.walletMap
45
+ }
46
+ });
47
+ ceremonyCeremonyCompleteResolver(undefined);
43
48
  }
44
49
  });
45
- if (!rawPublicKey || !(rawPublicKey instanceof Uint8Array)) {
46
- throw new Error('Raw public key is not a Uint8Array');
50
+ // Wait for the ceremony to complete before proceeding
51
+ await ceremonyCompletePromise;
52
+ if (!rawPublicKey || !(rawPublicKey instanceof Uint8Array || typeof rawPublicKey === 'string')) {
53
+ throw new Error('Raw public key is not a Uint8Array or string' + typeof rawPublicKey);
47
54
  }
48
55
  if (!clientKeyShares) {
49
- throw new Error('Error creating wallet account');
56
+ throw new Error(ERROR_KEYGEN_FAILED);
50
57
  }
51
58
  const { accountAddress } = await this.deriveAccountAddress(rawPublicKey);
52
59
  // Update client key shares in wallet map
53
- // warning: this might result in race condition if `onCeremonyComplete` executes at the same time
54
- // TODO: remove this once iframe handling for secret shares is implemented
55
60
  await this.setClientKeySharesToLocalStorage({
56
61
  accountAddress,
57
62
  clientKeyShares,
58
63
  overwriteOrMerge: 'overwrite'
59
64
  });
60
- // Backup the new wallet without waiting for the promise to resolve
61
- void this.storeEncryptedBackupByWalletWithRetry({
65
+ await this.storeEncryptedBackupByWalletWithRetry({
62
66
  accountAddress,
63
67
  clientKeyShares,
64
- password
68
+ password,
69
+ signedSessionId
65
70
  });
66
71
  return {
67
72
  accountAddress,
68
- rawPublicKey: rawPublicKey,
69
- clientKeyShares
73
+ rawPublicKey
70
74
  };
71
75
  } catch (error) {
72
76
  this.logger.error(ERROR_CREATE_WALLET_ACCOUNT, error);
73
77
  throw new Error(ERROR_CREATE_WALLET_ACCOUNT);
74
78
  }
75
79
  }
76
- // Function to properly derive account address
77
80
  async deriveAccountAddress(rawPublicKey) {
78
- const accountAddress = bs58.encode(rawPublicKey);
81
+ const pubKeyBytes = typeof rawPublicKey === 'string' ? new Uint8Array(Buffer.from(rawPublicKey, 'hex')) : rawPublicKey;
82
+ const accountAddress = bs58.encode(pubKeyBytes);
79
83
  return {
80
84
  accountAddress
81
85
  };
@@ -86,62 +90,55 @@ class DynamicSvmWalletClient extends DynamicWalletClient {
86
90
  * @param message The message to sign (Uint8Array)
87
91
  * @param accountAddress Solana address (base58 encoded)
88
92
  * @param password The password for encrypted backup shares
89
- */ async signMessage({ message, accountAddress, password = undefined }) {
93
+ */ async signMessage({ message, accountAddress, password = undefined, signedSessionId, mfaToken }) {
90
94
  await this.verifyPassword({
91
95
  accountAddress,
92
96
  password,
93
- walletOperation: WalletOperation.SIGN_MESSAGE
97
+ walletOperation: WalletOperation.SIGN_MESSAGE,
98
+ signedSessionId
94
99
  });
95
100
  if (!accountAddress) {
96
- throw new Error('Account address is required');
101
+ throw new Error(ERROR_ACCOUNT_ADDRESS_REQUIRED);
97
102
  }
98
103
  try {
99
104
  const signatureEd25519 = await this.sign({
100
105
  message,
101
106
  accountAddress: accountAddress,
102
107
  chainName: this.chainName,
103
- password
108
+ password,
109
+ signedSessionId,
110
+ mfaToken
104
111
  });
105
112
  const base58Signature = bs58.encode(signatureEd25519);
106
113
  return base58Signature;
107
114
  } catch (error) {
108
- this.logger.error('Error signing message:', error);
109
- throw error;
115
+ this.logger.error(ERROR_SIGN_MESSAGE, error);
116
+ throw new Error(ERROR_SIGN_MESSAGE);
110
117
  }
111
118
  }
112
- async signTransaction({ senderAddress, transaction, password = undefined }) {
119
+ async signTransaction({ senderAddress, transaction, password = undefined, signedSessionId, mfaToken, chainId }) {
113
120
  await this.verifyPassword({
114
121
  accountAddress: senderAddress,
115
122
  password,
116
- walletOperation: WalletOperation.SIGN_TRANSACTION
123
+ walletOperation: WalletOperation.SIGN_TRANSACTION,
124
+ signedSessionId
117
125
  });
118
126
  try {
119
- let messageToSign;
120
- if (transaction instanceof VersionedTransaction) {
121
- // For versioned transactions, we need to sign the message directly
122
- const messageBytes = transaction.message.serialize();
123
- messageToSign = Buffer.from(messageBytes).toString('hex');
124
- } else {
125
- // For legacy transactions, serialize the message
126
- const messageBytes = transaction.serializeMessage();
127
- messageToSign = Buffer.from(messageBytes).toString('hex');
128
- }
129
- const signatureEd25519 = await this.sign({
130
- message: messageToSign,
131
- accountAddress: senderAddress,
132
- chainName: this.chainName,
133
- password
127
+ const base58SerializedTransaction = this.prepareTransactionForSigning(transaction);
128
+ const signParams = this.buildSignParams({
129
+ transaction,
130
+ senderAddress,
131
+ password,
132
+ signedSessionId,
133
+ mfaToken,
134
+ chainId,
135
+ base58SerializedTransaction
134
136
  });
137
+ const signatureEd25519 = await this.sign(signParams);
135
138
  if (!signatureEd25519) {
136
139
  throw new Error('Signature is undefined');
137
140
  }
138
- const senderPublicKey = new PublicKey(senderAddress);
139
- const signedTransaction = addSignatureToTransaction({
140
- transaction,
141
- signature: signatureEd25519,
142
- signerPublicKey: senderPublicKey
143
- });
144
- return signedTransaction;
141
+ return Buffer.from(signatureEd25519).toString('hex');
145
142
  } catch (error) {
146
143
  this.logger.error('Error in signTransaction:', error);
147
144
  if (error instanceof Error) {
@@ -150,32 +147,59 @@ class DynamicSvmWalletClient extends DynamicWalletClient {
150
147
  throw error;
151
148
  }
152
149
  }
150
+ prepareTransactionForSigning(transaction) {
151
+ const transactionBytes = new Uint8Array(Buffer.from(transaction, 'hex'));
152
+ const deserializedTransaction = VersionedMessage.deserialize(transactionBytes);
153
+ const versionedTransaction = new VersionedTransaction(deserializedTransaction);
154
+ const serializedTransaction = versionedTransaction.serialize();
155
+ return bs58.encode(serializedTransaction);
156
+ }
157
+ buildSignParams({ transaction, senderAddress, password, signedSessionId, mfaToken, chainId, base58SerializedTransaction }) {
158
+ const signParams = {
159
+ message: transaction,
160
+ accountAddress: senderAddress,
161
+ chainName: this.chainName,
162
+ password,
163
+ signedSessionId,
164
+ mfaToken
165
+ };
166
+ if (chainId !== undefined) {
167
+ signParams.context = {
168
+ svmTransaction: {
169
+ chainId,
170
+ method: 'signAndSendTransaction',
171
+ serializedTransactions: [
172
+ base58SerializedTransaction
173
+ ]
174
+ }
175
+ };
176
+ }
177
+ return signParams;
178
+ }
153
179
  /**
154
180
  * Exports the private key for a given account address
155
181
  *
156
182
  * @param accountAddress The account address to export the private key for
157
183
  * @param password The password for encrypted backup shares
158
184
  * @returns The private key
159
- */ async exportPrivateKey({ accountAddress, displayContainer, password = undefined }) {
185
+ */ async exportPrivateKey({ accountAddress, password = undefined, signedSessionId, mfaToken }) {
160
186
  await this.verifyPassword({
161
187
  accountAddress,
162
188
  password,
163
- walletOperation: WalletOperation.EXPORT_PRIVATE_KEY
189
+ walletOperation: WalletOperation.EXPORT_PRIVATE_KEY,
190
+ signedSessionId
164
191
  });
165
192
  const { derivedPrivateKey } = await this.exportKey({
166
193
  accountAddress,
167
194
  chainName: this.chainName,
168
- password
195
+ password,
196
+ signedSessionId,
197
+ mfaToken
169
198
  });
170
199
  if (!derivedPrivateKey) {
171
200
  throw new Error('Derived private key is undefined');
172
201
  }
173
- const encodedPrivateKey = bs58.encode(Buffer.from(derivedPrivateKey));
174
- // Display the private key in the container via iframe
175
- const { iframeDisplay } = await this.initializeIframeDisplayForContainer({
176
- container: displayContainer
177
- });
178
- iframeDisplay.displayPrivateKey(encodedPrivateKey);
202
+ return derivedPrivateKey;
179
203
  }
180
204
  /**
181
205
  * Exports the private key for a given account address
@@ -219,65 +243,89 @@ class DynamicSvmWalletClient extends DynamicWalletClient {
219
243
  * @param thresholdSignatureScheme The threshold signature scheme to use
220
244
  * @param password The password for encrypted backup shares
221
245
  * @returns The account address, raw public key, and client key shares
222
- */ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError }) {
223
- //get public key from private key
224
- const publicKey = this.getPublicKeyFromPrivateKey(privateKey);
225
- const formattedPrivateKey = await this.decodePrivateKeyForSolana(privateKey);
226
- const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
227
- chainName,
228
- privateKey: formattedPrivateKey,
229
- thresholdSignatureScheme,
230
- onError,
231
- onCeremonyComplete: (accountAddress, walletId)=>{
232
- // update wallet map
233
- this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
234
- accountAddress,
235
- walletId,
236
- chainName: this.chainName,
237
- thresholdSignatureScheme,
238
- clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
239
- });
246
+ */ async importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password = undefined, onError, signedSessionId }) {
247
+ try {
248
+ let ceremonyCeremonyCompleteResolver;
249
+ const ceremonyCompletePromise = new Promise((resolve)=>{
250
+ ceremonyCeremonyCompleteResolver = resolve;
251
+ });
252
+ //get public key from private key
253
+ const publicKey = this.getPublicKeyFromPrivateKey(privateKey);
254
+ const formattedPrivateKey = this.decodePrivateKeyForSolana(privateKey);
255
+ const { rawPublicKey, clientKeyShares } = await this.importRawPrivateKey({
256
+ chainName,
257
+ privateKey: formattedPrivateKey,
258
+ thresholdSignatureScheme,
259
+ onError: (error)=>{
260
+ this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
261
+ onError == null ? void 0 : onError(error);
262
+ },
263
+ onCeremonyComplete: (accountAddress, walletId)=>{
264
+ // update wallet map
265
+ this.walletMap[accountAddress] = _extends({}, this.walletMap[accountAddress] || {}, {
266
+ accountAddress,
267
+ walletId,
268
+ chainName: this.chainName,
269
+ thresholdSignatureScheme,
270
+ clientKeySharesBackupInfo: getClientKeyShareBackupInfo()
271
+ });
272
+ this.logger.debug('walletMap updated for wallet', {
273
+ context: {
274
+ accountAddress,
275
+ walletId,
276
+ walletMap: this.walletMap
277
+ }
278
+ });
279
+ ceremonyCeremonyCompleteResolver(undefined);
280
+ }
281
+ });
282
+ // Wait for the ceremony to complete before proceeding
283
+ await ceremonyCompletePromise;
284
+ if (!rawPublicKey || !clientKeyShares) {
285
+ throw new Error(ERROR_IMPORT_PRIVATE_KEY);
240
286
  }
241
- });
242
- if (!rawPublicKey || !clientKeyShares) {
243
- throw new Error('Error creating wallet account');
244
- }
245
- const { accountAddress } = await this.deriveAccountAddress(rawPublicKey);
246
- if (accountAddress !== publicKey) {
247
- throw new Error(`Public key mismatch: derived address ${accountAddress} !== public key ${publicKey}`);
287
+ const { accountAddress } = await this.deriveAccountAddress(rawPublicKey);
288
+ if (accountAddress !== publicKey) {
289
+ throw new Error(`Public key mismatch: derived address ${accountAddress} !== public key ${publicKey}`);
290
+ }
291
+ // Update client key shares in wallet map
292
+ await this.setClientKeySharesToLocalStorage({
293
+ accountAddress,
294
+ clientKeyShares,
295
+ overwriteOrMerge: 'overwrite'
296
+ });
297
+ await this.storeEncryptedBackupByWalletWithRetry({
298
+ accountAddress,
299
+ clientKeyShares,
300
+ password,
301
+ signedSessionId
302
+ });
303
+ return {
304
+ accountAddress,
305
+ rawPublicKey: rawPublicKey
306
+ };
307
+ } catch (error) {
308
+ this.logger.error(ERROR_IMPORT_PRIVATE_KEY, error);
309
+ throw new Error(ERROR_IMPORT_PRIVATE_KEY);
248
310
  }
249
- // Update client key shares in wallet map
250
- // warning: this might result in race condition if `onCeremonyComplete` executes at the same time
251
- // TODO: remove this once iframe handling for secret shares is implemented
252
- await this.setClientKeySharesToLocalStorage({
253
- accountAddress,
254
- clientKeyShares,
255
- overwriteOrMerge: 'overwrite'
256
- });
257
- // Backup the new wallet without waiting for the promise to resolve
258
- void this.storeEncryptedBackupByWalletWithRetry({
259
- accountAddress,
260
- clientKeyShares,
261
- password
262
- });
263
- return {
264
- accountAddress,
265
- rawPublicKey: rawPublicKey,
266
- clientKeyShares
267
- };
268
311
  }
269
312
  async getSvmWallets() {
270
313
  const wallets = await this.getWallets();
271
314
  const svmWallets = wallets.filter((wallet)=>wallet.chainName === 'solana');
272
315
  return svmWallets;
273
316
  }
274
- constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl }){
317
+ constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, featureFlags, authMode = AuthMode.HEADER, sdkVersion }){
275
318
  super({
276
319
  environmentId,
277
320
  authToken,
278
321
  baseApiUrl,
279
- baseMPCRelayApiUrl
280
- }), this.chainName = 'SOL';
322
+ baseMPCRelayApiUrl,
323
+ storageKey,
324
+ debug,
325
+ featureFlags,
326
+ authMode,
327
+ sdkVersion
328
+ }), this.chainName = 'SVM';
281
329
  }
282
330
  }
283
331
 
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@dynamic-labs-wallet/svm",
3
- "version": "0.0.0-preview.160.0",
3
+ "version": "0.0.1",
4
4
  "license": "MIT",
5
+ "type": "commonjs",
5
6
  "dependencies": {
6
- "@dynamic-labs-wallet/browser": "0.0.0-preview.160.0",
7
+ "@dynamic-labs-wallet/browser": "0.0.1",
8
+ "@dynamic-labs/sdk-api-core": "^0.0.753",
7
9
  "@solana/web3.js": "^1.98.2",
8
10
  "bs58": "^6.0.0"
9
11
  },
@@ -24,7 +26,7 @@
24
26
  "types": "./index.esm.d.ts",
25
27
  "import": "./index.esm.js",
26
28
  "require": "./index.cjs.js",
27
- "default": "./index.cjs.js"
29
+ "default": "./index.esm.js"
28
30
  }
29
31
  }
30
32
  }
@@ -1,29 +1,23 @@
1
- import { ClientKeyShare, DynamicWalletClient, Ed25519KeygenResult, ThresholdSignatureScheme } from '@dynamic-labs-wallet/browser';
2
- import { Transaction, VersionedTransaction } from '@solana/web3.js';
1
+ import { DynamicWalletClient, DynamicWalletClientProps, Ed25519KeygenResult, ThresholdSignatureScheme } from '@dynamic-labs-wallet/browser';
3
2
  export declare class DynamicSvmWalletClient extends DynamicWalletClient {
4
- readonly chainName = "SOL";
3
+ readonly chainName = "SVM";
5
4
  accountAddress?: string;
6
- constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, }: {
7
- environmentId: string;
8
- authToken: string;
9
- baseApiUrl?: string;
10
- baseMPCRelayApiUrl?: string;
11
- });
5
+ constructor({ environmentId, authToken, baseApiUrl, baseMPCRelayApiUrl, storageKey, debug, featureFlags, authMode, sdkVersion, }: DynamicWalletClientProps);
12
6
  /**
13
7
  * Creates a wallet account on the Solana chain
14
8
  *
15
9
  * @param thresholdSignatureScheme The threshold signature scheme to use
16
10
  * @returns The account address, public key hex, raw public key, and client key shares
17
11
  */
18
- createWalletAccount({ thresholdSignatureScheme, password, }: {
12
+ createWalletAccount({ thresholdSignatureScheme, password, signedSessionId, }: {
19
13
  thresholdSignatureScheme: ThresholdSignatureScheme;
20
14
  password?: string;
15
+ signedSessionId: string;
21
16
  }): Promise<{
22
17
  accountAddress: string;
23
- rawPublicKey: Uint8Array;
24
- clientKeyShares: ClientKeyShare[];
18
+ rawPublicKey: Uint8Array | string;
25
19
  }>;
26
- deriveAccountAddress(rawPublicKey: Uint8Array): Promise<{
20
+ deriveAccountAddress(rawPublicKey: string | Uint8Array): Promise<{
27
21
  accountAddress: string;
28
22
  }>;
29
23
  /**
@@ -33,16 +27,23 @@ export declare class DynamicSvmWalletClient extends DynamicWalletClient {
33
27
  * @param accountAddress Solana address (base58 encoded)
34
28
  * @param password The password for encrypted backup shares
35
29
  */
36
- signMessage({ message, accountAddress, password, }: {
30
+ signMessage({ message, accountAddress, password, signedSessionId, mfaToken, }: {
37
31
  message: string;
38
32
  accountAddress: string;
39
33
  password?: string;
34
+ signedSessionId: string;
35
+ mfaToken?: string;
40
36
  }): Promise<string>;
41
- signTransaction({ senderAddress, transaction, password, }: {
37
+ signTransaction({ senderAddress, transaction, password, signedSessionId, mfaToken, chainId, }: {
42
38
  senderAddress: string;
43
- transaction: VersionedTransaction | Transaction;
39
+ transaction: string;
44
40
  password?: string;
45
- }): Promise<VersionedTransaction | Transaction>;
41
+ signedSessionId: string;
42
+ mfaToken?: string;
43
+ chainId?: string;
44
+ }): Promise<string>;
45
+ private prepareTransactionForSigning;
46
+ private buildSignParams;
46
47
  /**
47
48
  * Exports the private key for a given account address
48
49
  *
@@ -50,11 +51,12 @@ export declare class DynamicSvmWalletClient extends DynamicWalletClient {
50
51
  * @param password The password for encrypted backup shares
51
52
  * @returns The private key
52
53
  */
53
- exportPrivateKey({ accountAddress, displayContainer, password, }: {
54
+ exportPrivateKey({ accountAddress, password, signedSessionId, mfaToken, }: {
54
55
  accountAddress: string;
55
- displayContainer: HTMLElement;
56
56
  password?: string;
57
- }): Promise<void>;
57
+ signedSessionId: string;
58
+ mfaToken?: string;
59
+ }): Promise<string>;
58
60
  /**
59
61
  * Exports the private key for a given account address
60
62
  *
@@ -85,17 +87,17 @@ export declare class DynamicSvmWalletClient extends DynamicWalletClient {
85
87
  * @param password The password for encrypted backup shares
86
88
  * @returns The account address, raw public key, and client key shares
87
89
  */
88
- importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, onError, }: {
90
+ importPrivateKey({ privateKey, chainName, thresholdSignatureScheme, password, onError, signedSessionId, }: {
89
91
  privateKey: string;
90
92
  chainName: string;
91
93
  thresholdSignatureScheme: ThresholdSignatureScheme;
92
94
  password?: string;
93
95
  onError?: (error: Error) => void;
96
+ signedSessionId: string;
94
97
  }): Promise<{
95
98
  accountAddress: string;
96
99
  rawPublicKey: Uint8Array | undefined;
97
- clientKeyShares: ClientKeyShare[];
98
100
  }>;
99
101
  getSvmWallets(): Promise<any>;
100
102
  }
101
- //# sourceMappingURL=svm.d.ts.map
103
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/svm/client.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- export * from './svm';
1
+ export * from './client';
2
2
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svm/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svm/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"svm.d.ts","sourceRoot":"","sources":["../../src/svm/svm.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,wBAAwB,EAGzB,MAAM,8BAA8B,CAAC;AAEtC,OAAO,EAEL,WAAW,EACX,oBAAoB,EAErB,MAAM,iBAAiB,CAAC;AAIzB,qBAAa,sBAAuB,SAAQ,mBAAmB;IAC7D,QAAQ,CAAC,SAAS,SAAS;IAC3B,cAAc,CAAC,EAAE,MAAM,CAAC;gBAEZ,EACV,aAAa,EACb,SAAS,EACT,UAAU,EACV,kBAAkB,GACnB,EAAE;QACD,aAAa,EAAE,MAAM,CAAC;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,kBAAkB,CAAC,EAAE,MAAM,CAAC;KAC7B;IASD;;;;;OAKG;IACG,mBAAmB,CAAC,EACxB,wBAAwB,EACxB,QAAoB,GACrB,EAAE;QACD,wBAAwB,EAAE,wBAAwB,CAAC;QACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QACV,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,UAAU,CAAC;QACzB,eAAe,EAAE,cAAc,EAAE,CAAC;KACnC,CAAC;IA0DI,oBAAoB,CAAC,YAAY,EAAE,UAAU;;;IAOnD;;;;;;OAMG;IACG,WAAW,CAAC,EAChB,OAAO,EACP,cAAc,EACd,QAAoB,GACrB,EAAE;QACD,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;IA2BK,eAAe,CAAC,EACpB,aAAa,EACb,WAAW,EACX,QAAoB,GACrB,EAAE;QACD,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,oBAAoB,GAAG,WAAW,CAAC;QAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC,oBAAoB,GAAG,WAAW,CAAC;IAgD/C;;;;;;OAMG;IACG,gBAAgB,CAAC,EACrB,cAAc,EACd,gBAAgB,EAChB,QAAoB,GACrB,EAAE;QACD,cAAc,EAAE,MAAM,CAAC;QACvB,gBAAgB,EAAE,WAAW,CAAC;QAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB;IAwBD;;;;;OAKG;IACG,uBAAuB,CAAC,EAC5B,SAAS,EACT,cAAc,GACf,EAAE;QACD,SAAS,EAAE,mBAAmB,EAAE,CAAC;QACjC,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB;;;IASD;;;;;OAKG;IACH,yBAAyB,CAAC,UAAU,EAAE,MAAM;IAM5C,0BAA0B,CAAC,UAAU,EAAE,MAAM;IAQ7C,eAAe,CAAC,SAAS,EAAE,UAAU,GAAG,MAAM;IAI9C;;;;;;;;OAQG;IACG,gBAAgB,CAAC,EACrB,UAAU,EACV,SAAS,EACT,wBAAwB,EACxB,QAAoB,EACpB,OAAO,GACR,EAAE;QACD,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,wBAAwB,EAAE,wBAAwB,CAAC;QACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;KAClC,GAAG,OAAO,CAAC;QACV,cAAc,EAAE,MAAM,CAAC;QACvB,YAAY,EAAE,UAAU,GAAG,SAAS,CAAC;QACrC,eAAe,EAAE,cAAc,EAAE,CAAC;KACnC,CAAC;IA6DI,aAAa;CAOpB"}