@dynamic-labs/embedded-wallet-solana 3.5.1 → 3.6.0

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/CHANGELOG.md CHANGED
@@ -1,4 +1,17 @@
1
1
 
2
+ ## [3.6.0](https://github.com/dynamic-labs/DynamicAuth/compare/v3.5.1...v3.6.0) (2024-11-07)
3
+
4
+
5
+ ### Features
6
+
7
+ * Add a confirmation UI modal for signAllTransactions and signTransaction for Solana Embedded wallets. UI update to the embedded wallet confirmation UI modal.([#7381](https://github.com/dynamic-labs/DynamicAuth/issues/7381)) ([abac247](https://github.com/dynamic-labs/DynamicAuth/commit/abac247c53171dc05443ce20b4f152e5f25f27e5))
8
+
9
+
10
+ ### Bug Fixes
11
+
12
+ * confirmation modal popup after send balance flow ([#7382](https://github.com/dynamic-labs/DynamicAuth/issues/7382)) ([72d5848](https://github.com/dynamic-labs/DynamicAuth/commit/72d5848be2466879f2b3efbaf5c13885752513b0))
13
+ * network switch in global connectivity prevented publicClient call ([#7377](https://github.com/dynamic-labs/DynamicAuth/issues/7377)) ([a588497](https://github.com/dynamic-labs/DynamicAuth/commit/a5884978cbe3f875cef7560a004a0b127432ea9e))
14
+
2
15
  ### [3.5.1](https://github.com/dynamic-labs/DynamicAuth/compare/v3.5.0...v3.5.1) (2024-11-05)
3
16
 
4
17
 
package/package.cjs CHANGED
@@ -3,14 +3,13 @@
3
3
 
4
4
  Object.defineProperty(exports, '__esModule', { value: true });
5
5
 
6
- var version = "3.5.1";
6
+ var version = "3.6.0";
7
7
  var dependencies = {
8
8
  "@dynamic-labs/sdk-api-core": "0.0.559",
9
- "@dynamic-labs/utils": "3.5.1",
10
- "@dynamic-labs/logger": "3.5.1",
11
- "@dynamic-labs/types": "3.5.1",
9
+ "@dynamic-labs/utils": "3.6.0",
10
+ "@dynamic-labs/logger": "3.6.0",
11
+ "@dynamic-labs/types": "3.6.0",
12
12
  eventemitter3: "5.0.1",
13
- "@solana/spl-token": "0.4.6",
14
13
  "@solana/web3.js": "1.92.1",
15
14
  "@turnkey/http": "2.12.2",
16
15
  "@turnkey/iframe-stamper": "2.0.0",
package/package.js CHANGED
@@ -1,12 +1,11 @@
1
1
  'use client'
2
- var version = "3.5.1";
2
+ var version = "3.6.0";
3
3
  var dependencies = {
4
4
  "@dynamic-labs/sdk-api-core": "0.0.559",
5
- "@dynamic-labs/utils": "3.5.1",
6
- "@dynamic-labs/logger": "3.5.1",
7
- "@dynamic-labs/types": "3.5.1",
5
+ "@dynamic-labs/utils": "3.6.0",
6
+ "@dynamic-labs/logger": "3.6.0",
7
+ "@dynamic-labs/types": "3.6.0",
8
8
  eventemitter3: "5.0.1",
9
- "@solana/spl-token": "0.4.6",
10
9
  "@solana/web3.js": "1.92.1",
11
10
  "@turnkey/http": "2.12.2",
12
11
  "@turnkey/iframe-stamper": "2.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dynamic-labs/embedded-wallet-solana",
3
- "version": "3.5.1",
3
+ "version": "3.6.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/dynamic-labs/dynamic-auth.git",
@@ -27,23 +27,22 @@
27
27
  },
28
28
  "dependencies": {
29
29
  "@dynamic-labs/sdk-api-core": "0.0.559",
30
- "@dynamic-labs/utils": "3.5.1",
31
- "@dynamic-labs/logger": "3.5.1",
32
- "@dynamic-labs/types": "3.5.1",
30
+ "@dynamic-labs/utils": "3.6.0",
31
+ "@dynamic-labs/logger": "3.6.0",
32
+ "@dynamic-labs/types": "3.6.0",
33
33
  "eventemitter3": "5.0.1",
34
- "@solana/spl-token": "0.4.6",
35
34
  "@solana/web3.js": "1.92.1",
36
35
  "@turnkey/http": "2.12.2",
37
36
  "@turnkey/iframe-stamper": "2.0.0",
38
37
  "@turnkey/solana": "0.3.9",
39
38
  "@turnkey/webauthn-stamper": "0.5.0",
40
- "@dynamic-labs/assert-package-version": "3.5.1",
41
- "@dynamic-labs/embedded-wallet": "3.5.1",
42
- "@dynamic-labs/rpc-providers": "3.5.1",
43
- "@dynamic-labs/solana-core": "3.5.1",
44
- "@dynamic-labs/wallet-book": "3.5.1",
45
- "@dynamic-labs/wallet-connector-core": "3.5.1",
46
- "@dynamic-labs/webauthn": "3.5.1",
39
+ "@dynamic-labs/assert-package-version": "3.6.0",
40
+ "@dynamic-labs/embedded-wallet": "3.6.0",
41
+ "@dynamic-labs/rpc-providers": "3.6.0",
42
+ "@dynamic-labs/solana-core": "3.6.0",
43
+ "@dynamic-labs/wallet-book": "3.6.0",
44
+ "@dynamic-labs/wallet-connector-core": "3.6.0",
45
+ "@dynamic-labs/webauthn": "3.6.0",
47
46
  "react-dom": "18.2.0",
48
47
  "viem": "2.9.25"
49
48
  },
@@ -14,7 +14,6 @@ var solanaCore = require('@dynamic-labs/solana-core');
14
14
  var utils = require('@dynamic-labs/utils');
15
15
  var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
16
16
  var createSolanaConnection = require('../utils/createSolanaConnection/createSolanaConnection.cjs');
17
- var transactionDecoder = require('../utils/transactionDecoder/transactionDecoder.cjs');
18
17
  var api = require('../utils/api/api.cjs');
19
18
  var TurnkeySolanaSigner = require('./TurnkeySolanaSigner.cjs');
20
19
 
@@ -263,7 +262,7 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
263
262
  return utils.bufferToBase64(signedRawMessage);
264
263
  });
265
264
  }
266
- signTransaction(transaction) {
265
+ internalSignTransaction(transaction) {
267
266
  return _tslib.__awaiter(this, void 0, void 0, function* () {
268
267
  yield this.createOrRestoreSession();
269
268
  let account = yield this.getTurnkeyAccount();
@@ -291,7 +290,34 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
291
290
  return transaction;
292
291
  });
293
292
  }
294
- signAllTransactions(transactions) {
293
+ signTransaction(transaction) {
294
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
295
+ if (!this.turnkeyAddress)
296
+ throw new utils.DynamicError('No turnkey account');
297
+ const uiTransaction = new solanaCore.SolanaUiTransaction({
298
+ connection: this.getConnection(),
299
+ from: this.turnkeyAddress,
300
+ onSubmit: () => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignTransaction(transaction); }),
301
+ });
302
+ return this.walletUiUtils.signTransaction(this, uiTransaction);
303
+ });
304
+ }
305
+ createUiTransaction(from) {
306
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
307
+ yield this.validateActiveWallet(from);
308
+ const transaction = new solanaCore.SolanaUiTransaction({
309
+ connection: this.getConnection(),
310
+ from,
311
+ onSubmit: (transaction) => _tslib.__awaiter(this, void 0, void 0, function* () {
312
+ if (!transaction)
313
+ return undefined;
314
+ return this.internalSignAndSendTransaction(transaction);
315
+ }),
316
+ });
317
+ return transaction;
318
+ });
319
+ }
320
+ internalSignAllTransactions(transactions) {
295
321
  return _tslib.__awaiter(this, void 0, void 0, function* () {
296
322
  yield this.createOrRestoreSession();
297
323
  let account = yield this.getTurnkeyAccount();
@@ -320,13 +346,26 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
320
346
  }
321
347
  });
322
348
  }
349
+ signAllTransactions(transactions) {
350
+ return _tslib.__awaiter(this, void 0, void 0, function* () {
351
+ if (!this.turnkeyAddress)
352
+ throw new utils.DynamicError('No turnkey account');
353
+ const uiTransaction = new solanaCore.SolanaUiTransaction({
354
+ connection: this.getConnection(),
355
+ from: this.turnkeyAddress,
356
+ multipleTransactions: transactions,
357
+ onSubmit: () => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignAllTransactions(transactions); }),
358
+ });
359
+ return this.walletUiUtils.signTransaction(this, uiTransaction);
360
+ });
361
+ }
323
362
  internalSignAndSendTransaction(transaction, options) {
324
363
  return _tslib.__awaiter(this, void 0, void 0, function* () {
325
364
  var _a, _b;
326
365
  if (!this.turnkeyAddress)
327
366
  throw new utils.DynamicError('Solana wallet not found');
328
367
  const currentConnection = this.getConnection((_b = (_a = this.connectionConfig) === null || _a === void 0 ? void 0 : _a.commitment) !== null && _b !== void 0 ? _b : 'confirmed');
329
- const signedTransaction = yield this.signTransaction(transaction);
368
+ const signedTransaction = yield this.internalSignTransaction(transaction);
330
369
  const signature = yield currentConnection.sendRawTransaction(signedTransaction.serialize(), options);
331
370
  // listen for tx confirmation until 60 seconds, which is ~150 blocks expiration
332
371
  return new Promise((resolve, reject) => {
@@ -347,52 +386,15 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
347
386
  }
348
387
  signAndSendTransaction(transaction, options) {
349
388
  return _tslib.__awaiter(this, void 0, void 0, function* () {
350
- var _a;
351
389
  if (!this.turnkeyAddress)
352
390
  throw new utils.DynamicError('Solana wallet not found');
353
- let optimizedTransaction = transaction;
354
- let alreadySigned = false;
355
- if ('version' in transaction) {
356
- alreadySigned = transaction.signatures.some((sig) => !sig.every((byte) => byte === 0));
357
- }
358
- else {
359
- alreadySigned = transaction.signatures.some((sig) => sig.signature);
360
- }
361
- try {
362
- // we cannot optimize partially signed transactions as once a tx is modified the signatures are no longer valid
363
- if ((yield this.getNetwork()) === 'mainnet' && !alreadySigned) {
364
- optimizedTransaction = (yield api.optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
365
- }
366
- }
367
- catch (e) {
368
- embeddedWallet.logger.warn('Failed to optimize transaction', e);
369
- }
370
- const transactionsData = yield transactionDecoder.decodeTransaction(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
371
- if (!(transactionsData === null || transactionsData === void 0 ? void 0 : transactionsData.length)) {
372
- throw new utils.DynamicError('Incorrectly formatted transaction instructions');
373
- }
374
- let spent;
375
- let insufficientFunds = false;
376
- try {
377
- spent = yield transactionDecoder.getTotalSolanaSpend(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
378
- }
379
- catch (e) {
380
- if (e.message === 'Insufficient funds') {
381
- insufficientFunds = true;
382
- }
383
- }
384
- const to = transactionDecoder.summarizeTransactionDecodedData(transactionsData);
391
+ const optimizedTransaction = yield this.optimizeTransaction(transaction);
385
392
  const uiTransaction = new solanaCore.SolanaUiTransaction({
386
393
  connection: this.getConnection(),
387
394
  from: this.turnkeyAddress,
395
+ multipleTransactions: [optimizedTransaction],
388
396
  onSubmit: () => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(optimizedTransaction, options); }),
389
- originalTransaction: optimizedTransaction,
390
397
  });
391
- uiTransaction.to = to;
392
- uiTransaction.value = spent;
393
- if (insufficientFunds) {
394
- uiTransaction.notEnoughFundsError = true;
395
- }
396
398
  // TODO: remove this. We should not be passing references to wallet connectors
397
399
  return this.walletUiUtils.sendTransaction(this, uiTransaction);
398
400
  });
@@ -435,16 +437,27 @@ class TurnkeySolanaWalletConnector extends embeddedWallet.TurnkeyWalletConnector
435
437
  lamportsToSol(lamports) {
436
438
  return lamports / web3_js.LAMPORTS_PER_SOL;
437
439
  }
438
- createUiTransaction(from) {
440
+ optimizeTransaction(transaction) {
439
441
  return _tslib.__awaiter(this, void 0, void 0, function* () {
440
- yield this.validateActiveWallet(from);
441
- const transaction = new solanaCore.SolanaUiTransaction({
442
- connection: this.getConnection(),
443
- from,
444
- onSubmit: (transaction) => _tslib.__awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(transaction); }),
445
- });
446
- transaction.feeDeducted = true;
447
- return transaction;
442
+ var _a;
443
+ let optimizedTransaction = transaction;
444
+ let alreadySigned = false;
445
+ if ('version' in transaction) {
446
+ alreadySigned = transaction.signatures.some((sig) => !sig.every((byte) => byte === 0));
447
+ }
448
+ else {
449
+ alreadySigned = transaction.signatures.some((sig) => sig.signature);
450
+ }
451
+ try {
452
+ // we cannot optimize partially signed transactions as once a tx is modified the signatures are no longer valid
453
+ if ((yield this.getNetwork()) === 'mainnet' && !alreadySigned) {
454
+ optimizedTransaction = (yield api.optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
455
+ }
456
+ }
457
+ catch (e) {
458
+ embeddedWallet.logger.warn('Failed to optimize transaction', e);
459
+ }
460
+ return optimizedTransaction;
448
461
  });
449
462
  }
450
463
  }
@@ -49,13 +49,16 @@ export declare class TurnkeySolanaWalletConnector extends TurnkeyWalletConnector
49
49
  signUint8ArrayMessage(encodedMessage: Uint8Array): Promise<Uint8Array>;
50
50
  getEnvId: () => any;
51
51
  signMessage(messageToSign: string): Promise<string | undefined>;
52
+ internalSignTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T>;
52
53
  signTransaction<T extends Transaction | VersionedTransaction>(transaction: T): Promise<T>;
54
+ createUiTransaction(from: string): Promise<IUITransaction>;
55
+ internalSignAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]>;
53
56
  signAllTransactions<T extends Transaction | VersionedTransaction>(transactions: T[]): Promise<T[]>;
54
57
  internalSignAndSendTransaction<T extends Transaction | VersionedTransaction>(transaction: T, options?: SendOptions): Promise<string>;
55
58
  signAndSendTransaction<T extends Transaction | VersionedTransaction>(transaction: T, options?: SendOptions): Promise<string>;
56
59
  sendTransaction<T extends Transaction | VersionedTransaction>(transaction: T, connection: Connection, options?: SendTransactionOptions): Promise<string>;
57
60
  private lamportsToSol;
58
- createUiTransaction(from: string): Promise<IUITransaction>;
61
+ private optimizeTransaction;
59
62
  stampCreateWalletAccountRequest: ({ request, }: {
60
63
  request: TurnkeyApiTypes['v1CreateWalletAccountsRequest'];
61
64
  }) => Promise<import("@turnkey/http").TSignedRequest>;
@@ -10,7 +10,6 @@ import { SolanaWallet, ProviderChain, getGenesisHashLSKey, SolanaUiTransaction }
10
10
  import { DynamicError, getTLD, PlatformService, bufferToBase64 } from '@dynamic-labs/utils';
11
11
  import { isSameAddress } from '@dynamic-labs/wallet-connector-core';
12
12
  import { createSolanaConnection } from '../utils/createSolanaConnection/createSolanaConnection.js';
13
- import { decodeTransaction, getTotalSolanaSpend, summarizeTransactionDecodedData } from '../utils/transactionDecoder/transactionDecoder.js';
14
13
  import { optimizeSolanaTransaction } from '../utils/api/api.js';
15
14
  import { TurnkeySolanaSigner } from './TurnkeySolanaSigner.js';
16
15
 
@@ -259,7 +258,7 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
259
258
  return bufferToBase64(signedRawMessage);
260
259
  });
261
260
  }
262
- signTransaction(transaction) {
261
+ internalSignTransaction(transaction) {
263
262
  return __awaiter(this, void 0, void 0, function* () {
264
263
  yield this.createOrRestoreSession();
265
264
  let account = yield this.getTurnkeyAccount();
@@ -287,7 +286,34 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
287
286
  return transaction;
288
287
  });
289
288
  }
290
- signAllTransactions(transactions) {
289
+ signTransaction(transaction) {
290
+ return __awaiter(this, void 0, void 0, function* () {
291
+ if (!this.turnkeyAddress)
292
+ throw new DynamicError('No turnkey account');
293
+ const uiTransaction = new SolanaUiTransaction({
294
+ connection: this.getConnection(),
295
+ from: this.turnkeyAddress,
296
+ onSubmit: () => __awaiter(this, void 0, void 0, function* () { return this.internalSignTransaction(transaction); }),
297
+ });
298
+ return this.walletUiUtils.signTransaction(this, uiTransaction);
299
+ });
300
+ }
301
+ createUiTransaction(from) {
302
+ return __awaiter(this, void 0, void 0, function* () {
303
+ yield this.validateActiveWallet(from);
304
+ const transaction = new SolanaUiTransaction({
305
+ connection: this.getConnection(),
306
+ from,
307
+ onSubmit: (transaction) => __awaiter(this, void 0, void 0, function* () {
308
+ if (!transaction)
309
+ return undefined;
310
+ return this.internalSignAndSendTransaction(transaction);
311
+ }),
312
+ });
313
+ return transaction;
314
+ });
315
+ }
316
+ internalSignAllTransactions(transactions) {
291
317
  return __awaiter(this, void 0, void 0, function* () {
292
318
  yield this.createOrRestoreSession();
293
319
  let account = yield this.getTurnkeyAccount();
@@ -316,13 +342,26 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
316
342
  }
317
343
  });
318
344
  }
345
+ signAllTransactions(transactions) {
346
+ return __awaiter(this, void 0, void 0, function* () {
347
+ if (!this.turnkeyAddress)
348
+ throw new DynamicError('No turnkey account');
349
+ const uiTransaction = new SolanaUiTransaction({
350
+ connection: this.getConnection(),
351
+ from: this.turnkeyAddress,
352
+ multipleTransactions: transactions,
353
+ onSubmit: () => __awaiter(this, void 0, void 0, function* () { return this.internalSignAllTransactions(transactions); }),
354
+ });
355
+ return this.walletUiUtils.signTransaction(this, uiTransaction);
356
+ });
357
+ }
319
358
  internalSignAndSendTransaction(transaction, options) {
320
359
  return __awaiter(this, void 0, void 0, function* () {
321
360
  var _a, _b;
322
361
  if (!this.turnkeyAddress)
323
362
  throw new DynamicError('Solana wallet not found');
324
363
  const currentConnection = this.getConnection((_b = (_a = this.connectionConfig) === null || _a === void 0 ? void 0 : _a.commitment) !== null && _b !== void 0 ? _b : 'confirmed');
325
- const signedTransaction = yield this.signTransaction(transaction);
364
+ const signedTransaction = yield this.internalSignTransaction(transaction);
326
365
  const signature = yield currentConnection.sendRawTransaction(signedTransaction.serialize(), options);
327
366
  // listen for tx confirmation until 60 seconds, which is ~150 blocks expiration
328
367
  return new Promise((resolve, reject) => {
@@ -343,52 +382,15 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
343
382
  }
344
383
  signAndSendTransaction(transaction, options) {
345
384
  return __awaiter(this, void 0, void 0, function* () {
346
- var _a;
347
385
  if (!this.turnkeyAddress)
348
386
  throw new DynamicError('Solana wallet not found');
349
- let optimizedTransaction = transaction;
350
- let alreadySigned = false;
351
- if ('version' in transaction) {
352
- alreadySigned = transaction.signatures.some((sig) => !sig.every((byte) => byte === 0));
353
- }
354
- else {
355
- alreadySigned = transaction.signatures.some((sig) => sig.signature);
356
- }
357
- try {
358
- // we cannot optimize partially signed transactions as once a tx is modified the signatures are no longer valid
359
- if ((yield this.getNetwork()) === 'mainnet' && !alreadySigned) {
360
- optimizedTransaction = (yield optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
361
- }
362
- }
363
- catch (e) {
364
- logger.warn('Failed to optimize transaction', e);
365
- }
366
- const transactionsData = yield decodeTransaction(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
367
- if (!(transactionsData === null || transactionsData === void 0 ? void 0 : transactionsData.length)) {
368
- throw new DynamicError('Incorrectly formatted transaction instructions');
369
- }
370
- let spent;
371
- let insufficientFunds = false;
372
- try {
373
- spent = yield getTotalSolanaSpend(optimizedTransaction, this.getConnection(), this.turnkeyAddress);
374
- }
375
- catch (e) {
376
- if (e.message === 'Insufficient funds') {
377
- insufficientFunds = true;
378
- }
379
- }
380
- const to = summarizeTransactionDecodedData(transactionsData);
387
+ const optimizedTransaction = yield this.optimizeTransaction(transaction);
381
388
  const uiTransaction = new SolanaUiTransaction({
382
389
  connection: this.getConnection(),
383
390
  from: this.turnkeyAddress,
391
+ multipleTransactions: [optimizedTransaction],
384
392
  onSubmit: () => __awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(optimizedTransaction, options); }),
385
- originalTransaction: optimizedTransaction,
386
393
  });
387
- uiTransaction.to = to;
388
- uiTransaction.value = spent;
389
- if (insufficientFunds) {
390
- uiTransaction.notEnoughFundsError = true;
391
- }
392
394
  // TODO: remove this. We should not be passing references to wallet connectors
393
395
  return this.walletUiUtils.sendTransaction(this, uiTransaction);
394
396
  });
@@ -431,16 +433,27 @@ class TurnkeySolanaWalletConnector extends TurnkeyWalletConnectorBase {
431
433
  lamportsToSol(lamports) {
432
434
  return lamports / LAMPORTS_PER_SOL;
433
435
  }
434
- createUiTransaction(from) {
436
+ optimizeTransaction(transaction) {
435
437
  return __awaiter(this, void 0, void 0, function* () {
436
- yield this.validateActiveWallet(from);
437
- const transaction = new SolanaUiTransaction({
438
- connection: this.getConnection(),
439
- from,
440
- onSubmit: (transaction) => __awaiter(this, void 0, void 0, function* () { return this.internalSignAndSendTransaction(transaction); }),
441
- });
442
- transaction.feeDeducted = true;
443
- return transaction;
438
+ var _a;
439
+ let optimizedTransaction = transaction;
440
+ let alreadySigned = false;
441
+ if ('version' in transaction) {
442
+ alreadySigned = transaction.signatures.some((sig) => !sig.every((byte) => byte === 0));
443
+ }
444
+ else {
445
+ alreadySigned = transaction.signatures.some((sig) => sig.signature);
446
+ }
447
+ try {
448
+ // we cannot optimize partially signed transactions as once a tx is modified the signatures are no longer valid
449
+ if ((yield this.getNetwork()) === 'mainnet' && !alreadySigned) {
450
+ optimizedTransaction = (yield optimizeSolanaTransaction(this.getEnvId(), transaction, (_a = this.turnkeyAddress) !== null && _a !== void 0 ? _a : ''));
451
+ }
452
+ }
453
+ catch (e) {
454
+ logger.warn('Failed to optimize transaction', e);
455
+ }
456
+ return optimizedTransaction;
444
457
  });
445
458
  }
446
459
  }
@@ -1,2 +1 @@
1
1
  export { createSolanaConnection } from './createSolanaConnection';
2
- export { decodeTransaction, summarizeTransactionDecodedData, getTotalSolanaSpend, } from './transactionDecoder';
@@ -1 +0,0 @@
1
- export { decodeTransaction, summarizeTransactionDecodedData, getTotalSolanaSpend, } from './transactionDecoder';
@@ -1,176 +0,0 @@
1
- 'use client'
2
- 'use strict';
3
-
4
- Object.defineProperty(exports, '__esModule', { value: true });
5
-
6
- var _tslib = require('../../../../_virtual/_tslib.cjs');
7
- var web3_js = require('@solana/web3.js');
8
- var splToken = require('@solana/spl-token');
9
- var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
10
- var utils = require('@dynamic-labs/utils');
11
-
12
- const getTotalSolanaSpend = (transaction, connection, thisAddress) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
13
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
14
- let simulation;
15
- let feePayer;
16
- if ('version' in transaction) {
17
- [feePayer] = transaction.message.staticAccountKeys;
18
- simulation = yield connection.simulateTransaction(transaction, {
19
- accounts: {
20
- addresses: feePayer.toBase58() && feePayer.toBase58() !== thisAddress
21
- ? [feePayer.toBase58(), thisAddress]
22
- : [thisAddress],
23
- encoding: 'base64',
24
- },
25
- replaceRecentBlockhash: true,
26
- });
27
- }
28
- else {
29
- feePayer =
30
- transaction.feePayer || transaction.instructions[0].keys[0].pubkey;
31
- simulation = yield connection.simulateTransaction(transaction, undefined, feePayer.toBase58() && feePayer.toBase58() !== thisAddress
32
- ? [feePayer, new web3_js.PublicKey(thisAddress)]
33
- : [new web3_js.PublicKey(thisAddress)]);
34
- }
35
- const previousBalance = yield connection.getBalance(new web3_js.PublicKey(thisAddress));
36
- if (!((_c = (_b = (_a = simulation === null || simulation === void 0 ? void 0 : simulation.value) === null || _a === void 0 ? void 0 : _a.accounts) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.lamports)) {
37
- walletConnectorCore.logger.debug('Transaction simulation failed', simulation);
38
- const instructionError = JSON.stringify({
39
- InstructionError: [
40
- 0,
41
- {
42
- Custom: 1,
43
- },
44
- ],
45
- });
46
- const insufficientFundsForRent = JSON.stringify({
47
- InsufficientFundsForRent: {
48
- account_index: 0,
49
- },
50
- });
51
- if (JSON.stringify(simulation === null || simulation === void 0 ? void 0 : simulation.value.err) === instructionError ||
52
- JSON.stringify(simulation === null || simulation === void 0 ? void 0 : simulation.value.err) === insufficientFundsForRent) {
53
- throw new Error('Insufficient funds');
54
- }
55
- return undefined;
56
- }
57
- // the last account will be the embedded wallet,
58
- // if there are two addresses the first will be gas-sponsoring so we dont want to calculate sol for that
59
- const totalSolTransfer = previousBalance -
60
- ((_g = (_f = (_e = (_d = simulation === null || simulation === void 0 ? void 0 : simulation.value) === null || _d === void 0 ? void 0 : _d.accounts) === null || _e === void 0 ? void 0 : _e[1]) === null || _f === void 0 ? void 0 : _f.lamports) !== null && _g !== void 0 ? _g : (_k = (_j = (_h = simulation === null || simulation === void 0 ? void 0 : simulation.value) === null || _h === void 0 ? void 0 : _h.accounts) === null || _j === void 0 ? void 0 : _j[0]) === null || _k === void 0 ? void 0 : _k.lamports);
61
- return BigInt(totalSolTransfer);
62
- });
63
- const decodeTransaction = (transaction, connection, thisAddress) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
64
- var _l;
65
- if (!transaction) {
66
- throw new utils.DynamicError('Transaction is required');
67
- }
68
- try {
69
- let decodedInstructions = [];
70
- if ('version' in transaction) {
71
- const lookupTableAddresses = transaction.message.addressTableLookups.map((lookup) => new web3_js.PublicKey(lookup.accountKey));
72
- // For non-simple SOL transfers, we need to fetch the lookup table accounts
73
- if (lookupTableAddresses.length > 0) {
74
- const lookupTables = yield Promise.all(lookupTableAddresses.map((address) => connection.getAddressLookupTable(address)));
75
- const lookupTableAccounts = lookupTables
76
- .filter((result) => result !== null)
77
- .map((result) => result.value);
78
- if (lookupTableAccounts.length > 0) {
79
- decodedInstructions = web3_js.TransactionMessage.decompile(transaction.message, {
80
- addressLookupTableAccounts: lookupTableAccounts,
81
- }).instructions;
82
- }
83
- }
84
- else {
85
- decodedInstructions = web3_js.TransactionMessage.decompile(transaction.message).instructions;
86
- }
87
- }
88
- else if (!transaction.instructions) {
89
- decodedInstructions = (_l = web3_js.Transaction.from(Buffer.from(transaction.serialize()))) === null || _l === void 0 ? void 0 : _l.instructions;
90
- }
91
- else {
92
- decodedInstructions = transaction.instructions;
93
- }
94
- if (!(decodedInstructions === null || decodedInstructions === void 0 ? void 0 : decodedInstructions.length)) {
95
- throw new utils.DynamicError('Bad formatted instruction');
96
- }
97
- const solTransfers = decodedInstructions.filter((instruction) => instruction.programId.equals(web3_js.SystemProgram.programId));
98
- // Non-SPL transfers, just SOL
99
- if (solTransfers.length > 0) {
100
- return solTransfers.map((decodedInstruction) => {
101
- let decodedTransferInstruction;
102
- try {
103
- decodedTransferInstruction =
104
- web3_js.SystemInstruction.decodeTransfer(decodedInstruction);
105
- }
106
- catch (e) {
107
- return { from: thisAddress, to: 'Unknown' };
108
- }
109
- return {
110
- from: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.fromPubkey.toBase58(),
111
- to: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.toPubkey.toBase58(),
112
- };
113
- });
114
- }
115
- // SPL transfers
116
- let splTransfers = yield Promise.all(decodedInstructions.map((instruction) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
117
- var _m, _o, _p, _q, _r, _s, _t;
118
- if (instruction.programId.equals(splToken.TOKEN_PROGRAM_ID)) {
119
- const decodedTokenInstruction = splToken.decodeTransferInstructionUnchecked(instruction);
120
- const { source, destination } = decodedTokenInstruction.keys;
121
- if (destination) {
122
- // For contract interactions, e.g., swaps, the destination is the turnkey address, flip sender and receiver
123
- if ((destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58()) === thisAddress) {
124
- return {
125
- from: thisAddress,
126
- to: source === null || source === void 0 ? void 0 : source.pubkey.toBase58(),
127
- };
128
- }
129
- // Pure SPL transfers, get the address from the destination token account to display to user
130
- const destinationAccountInfo = yield connection.getParsedAccountInfo(destination.pubkey);
131
- const isTokenAccount = ((_p = (_o = (_m = destinationAccountInfo.value) === null || _m === void 0 ? void 0 : _m.data) === null || _o === void 0 ? void 0 : _o.parsed) === null || _p === void 0 ? void 0 : _p.type) === 'account';
132
- const destinationOwner = isTokenAccount
133
- ? (_t = (_s = (_r = (_q = destinationAccountInfo.value) === null || _q === void 0 ? void 0 : _q.data) === null || _r === void 0 ? void 0 : _r.parsed) === null || _s === void 0 ? void 0 : _s.info) === null || _t === void 0 ? void 0 : _t.owner
134
- : null;
135
- const toAddress = destinationOwner
136
- ? destinationOwner
137
- : destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58();
138
- return {
139
- from: thisAddress,
140
- to: toAddress,
141
- };
142
- }
143
- }
144
- return null;
145
- })));
146
- splTransfers = splTransfers.filter((transfer) => transfer !== null);
147
- if (splTransfers === null || splTransfers === void 0 ? void 0 : splTransfers.length)
148
- return splTransfers;
149
- // Return program IDs for non-SOL and non-SPL transfers
150
- const noTransferDestinations = decodedInstructions.map((instruction) => ({
151
- from: thisAddress,
152
- to: instruction.programId.toBase58(),
153
- }));
154
- if (noTransferDestinations.length)
155
- return noTransferDestinations;
156
- return [{ from: thisAddress, to: 'Unknown' }];
157
- }
158
- catch (error) {
159
- walletConnectorCore.logger.warn('[decodeTransaction]', error);
160
- return [{ from: thisAddress, to: 'Unknown' }];
161
- }
162
- });
163
- const summarizeTransactionDecodedData = (transactionsData) => {
164
- const recipients = new Set();
165
- transactionsData.forEach((transactionData) => {
166
- if (transactionData && transactionData.to) {
167
- recipients.add(transactionData.to);
168
- }
169
- });
170
- const to = recipients.size === 1 ? recipients.values().next().value : 'Multiple';
171
- return to;
172
- };
173
-
174
- exports.decodeTransaction = decodeTransaction;
175
- exports.getTotalSolanaSpend = getTotalSolanaSpend;
176
- exports.summarizeTransactionDecodedData = summarizeTransactionDecodedData;
@@ -1,12 +0,0 @@
1
- import { Transaction, VersionedTransaction, Connection } from '@solana/web3.js';
2
- type DestinationAndFrom = {
3
- to: string;
4
- from: string;
5
- };
6
- export declare const getTotalSolanaSpend: (transaction: Transaction | VersionedTransaction, connection: Connection, thisAddress: string) => Promise<bigint | undefined>;
7
- export declare const decodeTransaction: (transaction: Transaction | VersionedTransaction, connection: Connection, thisAddress: string) => Promise<Array<DestinationAndFrom>>;
8
- export declare const summarizeTransactionDecodedData: (transactionsData: {
9
- to: string;
10
- from: string;
11
- }[]) => any;
12
- export {};
@@ -1,170 +0,0 @@
1
- 'use client'
2
- import { __awaiter } from '../../../../_virtual/_tslib.js';
3
- import { PublicKey, TransactionMessage, Transaction, SystemProgram, SystemInstruction } from '@solana/web3.js';
4
- import { TOKEN_PROGRAM_ID, decodeTransferInstructionUnchecked } from '@solana/spl-token';
5
- import { logger } from '@dynamic-labs/wallet-connector-core';
6
- import { DynamicError } from '@dynamic-labs/utils';
7
-
8
- const getTotalSolanaSpend = (transaction, connection, thisAddress) => __awaiter(void 0, void 0, void 0, function* () {
9
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
10
- let simulation;
11
- let feePayer;
12
- if ('version' in transaction) {
13
- [feePayer] = transaction.message.staticAccountKeys;
14
- simulation = yield connection.simulateTransaction(transaction, {
15
- accounts: {
16
- addresses: feePayer.toBase58() && feePayer.toBase58() !== thisAddress
17
- ? [feePayer.toBase58(), thisAddress]
18
- : [thisAddress],
19
- encoding: 'base64',
20
- },
21
- replaceRecentBlockhash: true,
22
- });
23
- }
24
- else {
25
- feePayer =
26
- transaction.feePayer || transaction.instructions[0].keys[0].pubkey;
27
- simulation = yield connection.simulateTransaction(transaction, undefined, feePayer.toBase58() && feePayer.toBase58() !== thisAddress
28
- ? [feePayer, new PublicKey(thisAddress)]
29
- : [new PublicKey(thisAddress)]);
30
- }
31
- const previousBalance = yield connection.getBalance(new PublicKey(thisAddress));
32
- if (!((_c = (_b = (_a = simulation === null || simulation === void 0 ? void 0 : simulation.value) === null || _a === void 0 ? void 0 : _a.accounts) === null || _b === void 0 ? void 0 : _b[0]) === null || _c === void 0 ? void 0 : _c.lamports)) {
33
- logger.debug('Transaction simulation failed', simulation);
34
- const instructionError = JSON.stringify({
35
- InstructionError: [
36
- 0,
37
- {
38
- Custom: 1,
39
- },
40
- ],
41
- });
42
- const insufficientFundsForRent = JSON.stringify({
43
- InsufficientFundsForRent: {
44
- account_index: 0,
45
- },
46
- });
47
- if (JSON.stringify(simulation === null || simulation === void 0 ? void 0 : simulation.value.err) === instructionError ||
48
- JSON.stringify(simulation === null || simulation === void 0 ? void 0 : simulation.value.err) === insufficientFundsForRent) {
49
- throw new Error('Insufficient funds');
50
- }
51
- return undefined;
52
- }
53
- // the last account will be the embedded wallet,
54
- // if there are two addresses the first will be gas-sponsoring so we dont want to calculate sol for that
55
- const totalSolTransfer = previousBalance -
56
- ((_g = (_f = (_e = (_d = simulation === null || simulation === void 0 ? void 0 : simulation.value) === null || _d === void 0 ? void 0 : _d.accounts) === null || _e === void 0 ? void 0 : _e[1]) === null || _f === void 0 ? void 0 : _f.lamports) !== null && _g !== void 0 ? _g : (_k = (_j = (_h = simulation === null || simulation === void 0 ? void 0 : simulation.value) === null || _h === void 0 ? void 0 : _h.accounts) === null || _j === void 0 ? void 0 : _j[0]) === null || _k === void 0 ? void 0 : _k.lamports);
57
- return BigInt(totalSolTransfer);
58
- });
59
- const decodeTransaction = (transaction, connection, thisAddress) => __awaiter(void 0, void 0, void 0, function* () {
60
- var _l;
61
- if (!transaction) {
62
- throw new DynamicError('Transaction is required');
63
- }
64
- try {
65
- let decodedInstructions = [];
66
- if ('version' in transaction) {
67
- const lookupTableAddresses = transaction.message.addressTableLookups.map((lookup) => new PublicKey(lookup.accountKey));
68
- // For non-simple SOL transfers, we need to fetch the lookup table accounts
69
- if (lookupTableAddresses.length > 0) {
70
- const lookupTables = yield Promise.all(lookupTableAddresses.map((address) => connection.getAddressLookupTable(address)));
71
- const lookupTableAccounts = lookupTables
72
- .filter((result) => result !== null)
73
- .map((result) => result.value);
74
- if (lookupTableAccounts.length > 0) {
75
- decodedInstructions = TransactionMessage.decompile(transaction.message, {
76
- addressLookupTableAccounts: lookupTableAccounts,
77
- }).instructions;
78
- }
79
- }
80
- else {
81
- decodedInstructions = TransactionMessage.decompile(transaction.message).instructions;
82
- }
83
- }
84
- else if (!transaction.instructions) {
85
- decodedInstructions = (_l = Transaction.from(Buffer.from(transaction.serialize()))) === null || _l === void 0 ? void 0 : _l.instructions;
86
- }
87
- else {
88
- decodedInstructions = transaction.instructions;
89
- }
90
- if (!(decodedInstructions === null || decodedInstructions === void 0 ? void 0 : decodedInstructions.length)) {
91
- throw new DynamicError('Bad formatted instruction');
92
- }
93
- const solTransfers = decodedInstructions.filter((instruction) => instruction.programId.equals(SystemProgram.programId));
94
- // Non-SPL transfers, just SOL
95
- if (solTransfers.length > 0) {
96
- return solTransfers.map((decodedInstruction) => {
97
- let decodedTransferInstruction;
98
- try {
99
- decodedTransferInstruction =
100
- SystemInstruction.decodeTransfer(decodedInstruction);
101
- }
102
- catch (e) {
103
- return { from: thisAddress, to: 'Unknown' };
104
- }
105
- return {
106
- from: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.fromPubkey.toBase58(),
107
- to: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.toPubkey.toBase58(),
108
- };
109
- });
110
- }
111
- // SPL transfers
112
- let splTransfers = yield Promise.all(decodedInstructions.map((instruction) => __awaiter(void 0, void 0, void 0, function* () {
113
- var _m, _o, _p, _q, _r, _s, _t;
114
- if (instruction.programId.equals(TOKEN_PROGRAM_ID)) {
115
- const decodedTokenInstruction = decodeTransferInstructionUnchecked(instruction);
116
- const { source, destination } = decodedTokenInstruction.keys;
117
- if (destination) {
118
- // For contract interactions, e.g., swaps, the destination is the turnkey address, flip sender and receiver
119
- if ((destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58()) === thisAddress) {
120
- return {
121
- from: thisAddress,
122
- to: source === null || source === void 0 ? void 0 : source.pubkey.toBase58(),
123
- };
124
- }
125
- // Pure SPL transfers, get the address from the destination token account to display to user
126
- const destinationAccountInfo = yield connection.getParsedAccountInfo(destination.pubkey);
127
- const isTokenAccount = ((_p = (_o = (_m = destinationAccountInfo.value) === null || _m === void 0 ? void 0 : _m.data) === null || _o === void 0 ? void 0 : _o.parsed) === null || _p === void 0 ? void 0 : _p.type) === 'account';
128
- const destinationOwner = isTokenAccount
129
- ? (_t = (_s = (_r = (_q = destinationAccountInfo.value) === null || _q === void 0 ? void 0 : _q.data) === null || _r === void 0 ? void 0 : _r.parsed) === null || _s === void 0 ? void 0 : _s.info) === null || _t === void 0 ? void 0 : _t.owner
130
- : null;
131
- const toAddress = destinationOwner
132
- ? destinationOwner
133
- : destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58();
134
- return {
135
- from: thisAddress,
136
- to: toAddress,
137
- };
138
- }
139
- }
140
- return null;
141
- })));
142
- splTransfers = splTransfers.filter((transfer) => transfer !== null);
143
- if (splTransfers === null || splTransfers === void 0 ? void 0 : splTransfers.length)
144
- return splTransfers;
145
- // Return program IDs for non-SOL and non-SPL transfers
146
- const noTransferDestinations = decodedInstructions.map((instruction) => ({
147
- from: thisAddress,
148
- to: instruction.programId.toBase58(),
149
- }));
150
- if (noTransferDestinations.length)
151
- return noTransferDestinations;
152
- return [{ from: thisAddress, to: 'Unknown' }];
153
- }
154
- catch (error) {
155
- logger.warn('[decodeTransaction]', error);
156
- return [{ from: thisAddress, to: 'Unknown' }];
157
- }
158
- });
159
- const summarizeTransactionDecodedData = (transactionsData) => {
160
- const recipients = new Set();
161
- transactionsData.forEach((transactionData) => {
162
- if (transactionData && transactionData.to) {
163
- recipients.add(transactionData.to);
164
- }
165
- });
166
- const to = recipients.size === 1 ? recipients.values().next().value : 'Multiple';
167
- return to;
168
- };
169
-
170
- export { decodeTransaction, getTotalSolanaSpend, summarizeTransactionDecodedData };