@dynamic-labs/embedded-wallet-solana 3.0.0-alpha.9 → 3.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.
Files changed (39) hide show
  1. package/CHANGELOG.md +628 -0
  2. package/package.cjs +22 -0
  3. package/package.js +17 -0
  4. package/package.json +15 -12
  5. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.cjs +4 -7
  6. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.d.ts +6 -5
  7. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.js +4 -7
  8. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.cjs +138 -39
  9. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.d.ts +16 -11
  10. package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.js +136 -37
  11. package/src/lib/utils/api/api.cjs +38 -0
  12. package/src/lib/utils/api/api.d.ts +4 -0
  13. package/src/lib/utils/api/api.js +32 -0
  14. package/src/lib/utils/api/events/DynamicEvents.d.ts +6 -0
  15. package/src/lib/utils/api/events/auth.d.ts +49 -0
  16. package/src/lib/utils/api/utils/ApiEndpoint.cjs +41 -0
  17. package/src/lib/utils/api/utils/ApiEndpoint.d.ts +7 -0
  18. package/src/lib/utils/api/utils/ApiEndpoint.js +39 -0
  19. package/src/lib/utils/api/utils/SdkApi.cjs +35 -0
  20. package/src/lib/utils/api/utils/SdkApi.d.ts +2 -0
  21. package/src/lib/utils/api/utils/SdkApi.js +31 -0
  22. package/src/lib/utils/api/utils/helpers.cjs +92 -0
  23. package/src/lib/utils/api/utils/helpers.d.ts +12 -0
  24. package/src/lib/utils/api/utils/helpers.js +81 -0
  25. package/src/lib/utils/api/utils/version.cjs +12 -0
  26. package/src/lib/utils/api/utils/version.d.ts +2 -0
  27. package/src/lib/utils/api/utils/version.js +7 -0
  28. package/src/lib/utils/index.d.ts +1 -2
  29. package/src/lib/utils/transactionDecoder/index.d.ts +1 -1
  30. package/src/lib/utils/transactionDecoder/transactionDecoder.cjs +127 -71
  31. package/src/lib/utils/transactionDecoder/transactionDecoder.d.ts +8 -6
  32. package/src/lib/utils/transactionDecoder/transactionDecoder.js +127 -72
  33. package/src/lib/constants.cjs +0 -8
  34. package/src/lib/constants.d.ts +0 -1
  35. package/src/lib/constants.js +0 -4
  36. package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.cjs +0 -10
  37. package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.d.ts +0 -1
  38. package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.js +0 -6
  39. package/src/lib/utils/getGenesisHashLSKey/index.d.ts +0 -1
@@ -0,0 +1,12 @@
1
+ import { MinifiedDynamicJwt } from '@dynamic-labs/sdk-api-core';
2
+ import { Logger } from '@dynamic-labs/logger';
3
+ export declare const logger: Logger;
4
+ export declare const AUTH_MIN_TOKEN = "dynamic_min_authentication_token";
5
+ export declare const AUTH_MIN_TOKEN_DEMO = "dynamic_min_authentication_token_demo";
6
+ export declare const DYNAMIC_STORE_DEMO = "dynamic_store_demo";
7
+ export declare const DYNAMIC_STORE = "dynamic_store";
8
+ export declare const isCookieEnabled: () => any;
9
+ export declare const parseToken: (token: string | null | undefined) => any;
10
+ export declare const decodeMinJwt: (token: string | null | undefined) => Omit<MinifiedDynamicJwt, 'jwt'> | undefined;
11
+ export declare const getMinAuthToken: () => string | undefined;
12
+ export declare const isMinAuthTokenExpired: (token: string) => boolean;
@@ -0,0 +1,81 @@
1
+ 'use client'
2
+ import { AuthStorageEnum, MinifiedDynamicJwtFromJSON } from '@dynamic-labs/sdk-api-core';
3
+ import { Logger } from '@dynamic-labs/logger';
4
+ import { StorageService } from '@dynamic-labs/utils';
5
+
6
+ const logger = new Logger('DynamicSDK');
7
+ const AUTH_MIN_TOKEN = 'dynamic_min_authentication_token';
8
+ const AUTH_MIN_TOKEN_DEMO = 'dynamic_min_authentication_token_demo';
9
+ const isCookieEnabled = () => {
10
+ var _a, _b, _c, _d;
11
+ let securitySettings = (_a = StorageService.getItem('dynamic_store')) !== null && _a !== void 0 ? _a : StorageService.getItem('dynamic_store_demo');
12
+ securitySettings = (_b = securitySettings === null || securitySettings === void 0 ? void 0 : securitySettings.settings) === null || _b === void 0 ? void 0 : _b.security;
13
+ if (!securitySettings)
14
+ return false;
15
+ // client uses Dynamic cookies
16
+ const dynamicCookiesEnabled = (((_c = securitySettings.auth) === null || _c === void 0 ? void 0 : _c.storage) || []).includes(AuthStorageEnum.Cookie);
17
+ // BYO JWT client puts their non-Dynamic JWT in a cookie
18
+ const byoJwtCookieEnabled = Boolean((_d = securitySettings.externalAuth) === null || _d === void 0 ? void 0 : _d.cookieName);
19
+ // should return true for both of these scenarios
20
+ // because we also need to do `credentials: true` in api.ts when
21
+ // a byo jwt client sets their named cookie for their jwt and
22
+ // needs to send it to our backend
23
+ return dynamicCookiesEnabled || byoJwtCookieEnabled;
24
+ };
25
+ const parseToken = (token) => {
26
+ var _a;
27
+ if (!token)
28
+ return undefined;
29
+ const base64 = (_a = token.split('.')[1]) === null || _a === void 0 ? void 0 : _a.replace(/-/g, '+').replace(/_/g, '/');
30
+ const jsonPayload = base64 &&
31
+ decodeURIComponent(atob(base64)
32
+ .split('')
33
+ .map((c) => `%${`00${c.charCodeAt(0).toString(16)}`.slice(-2)}`)
34
+ .join(''));
35
+ return JSON.parse(jsonPayload);
36
+ };
37
+ const decodeMinJwt = (token) => {
38
+ try {
39
+ const json = parseToken(token);
40
+ if (!json)
41
+ return undefined;
42
+ return MinifiedDynamicJwtFromJSON(json);
43
+ }
44
+ catch (e) {
45
+ logger.error(e);
46
+ return undefined;
47
+ }
48
+ };
49
+ const getMinAuthToken = () => {
50
+ var _a;
51
+ if (typeof window === 'undefined')
52
+ return undefined;
53
+ const token = (_a = StorageService.getItem(AUTH_MIN_TOKEN, {
54
+ priority: ['secureStorage', 'localStorage'],
55
+ })) !== null && _a !== void 0 ? _a : StorageService.getItem(AUTH_MIN_TOKEN_DEMO, {
56
+ priority: ['secureStorage', 'localStorage'],
57
+ });
58
+ if (!token || isMinAuthTokenExpired(token))
59
+ return undefined;
60
+ return token;
61
+ };
62
+ const isMinAuthTokenExpired = (token) => {
63
+ const decoded = decodeMinJwt(token);
64
+ return isTokenExpired(decoded);
65
+ };
66
+ const isTokenExpired = (decoded) => {
67
+ if (!decoded) {
68
+ return true;
69
+ }
70
+ if (!decoded.exp) {
71
+ return true;
72
+ }
73
+ const expirationTime = new Date(decoded.exp * 1000).getTime();
74
+ const currentTime = new Date().getTime();
75
+ if (currentTime >= expirationTime) {
76
+ return true;
77
+ }
78
+ return false;
79
+ };
80
+
81
+ export { AUTH_MIN_TOKEN, AUTH_MIN_TOKEN_DEMO, decodeMinJwt, getMinAuthToken, isCookieEnabled, isMinAuthTokenExpired, logger, parseToken };
@@ -0,0 +1,12 @@
1
+ 'use client'
2
+ 'use strict';
3
+
4
+ Object.defineProperty(exports, '__esModule', { value: true });
5
+
6
+ var _package = require('../../../../../package.cjs');
7
+
8
+ const VERSION = _package.version;
9
+ const API_VERSION = _package.dependencies['@dynamic-labs/sdk-api-core'];
10
+
11
+ exports.API_VERSION = API_VERSION;
12
+ exports.VERSION = VERSION;
@@ -0,0 +1,2 @@
1
+ export declare const VERSION: string;
2
+ export declare const API_VERSION: string;
@@ -0,0 +1,7 @@
1
+ 'use client'
2
+ import { version, dependencies } from '../../../../../package.js';
3
+
4
+ const VERSION = version;
5
+ const API_VERSION = dependencies['@dynamic-labs/sdk-api-core'];
6
+
7
+ export { API_VERSION, VERSION };
@@ -1,3 +1,2 @@
1
1
  export { createSolanaConnection } from './createSolanaConnection';
2
- export { getGenesisHashLSKey } from './getGenesisHashLSKey';
3
- export { decodeTransaction, summarizeTransactionDecodedData, } from './transactionDecoder';
2
+ export { decodeTransaction, summarizeTransactionDecodedData, getTotalSolanaSpend, } from './transactionDecoder';
@@ -1 +1 @@
1
- export { decodeTransaction, summarizeTransactionDecodedData, } from './transactionDecoder';
1
+ export { decodeTransaction, summarizeTransactionDecodedData, getTotalSolanaSpend, } from './transactionDecoder';
@@ -6,101 +6,157 @@ Object.defineProperty(exports, '__esModule', { value: true });
6
6
  var _tslib = require('../../../../_virtual/_tslib.cjs');
7
7
  var web3_js = require('@solana/web3.js');
8
8
  var splToken = require('@solana/spl-token');
9
+ var walletConnectorCore = require('@dynamic-labs/wallet-connector-core');
9
10
  var utils = require('@dynamic-labs/utils');
10
11
 
12
+ const getTotalSolanaSpend = (transaction, connection, thisAddress) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
13
+ var _a, _b, _c, _d, _e, _f;
14
+ let simulation;
15
+ if ('version' in transaction) {
16
+ simulation = yield connection.simulateTransaction(transaction, {
17
+ accounts: { addresses: [thisAddress], encoding: 'base64' },
18
+ replaceRecentBlockhash: true,
19
+ });
20
+ }
21
+ else {
22
+ simulation = yield connection.simulateTransaction(transaction, undefined, [new web3_js.PublicKey(thisAddress)]);
23
+ }
24
+ const previousBalance = yield connection.getBalance(new web3_js.PublicKey(thisAddress));
25
+ 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)) {
26
+ walletConnectorCore.logger.debug('Transaction simulation failed', simulation);
27
+ const instructionError = JSON.stringify({
28
+ InstructionError: [
29
+ 0,
30
+ {
31
+ Custom: 1,
32
+ },
33
+ ],
34
+ });
35
+ const insufficientFundsForRent = JSON.stringify({
36
+ InsufficientFundsForRent: {
37
+ account_index: 0,
38
+ },
39
+ });
40
+ if (JSON.stringify(simulation === null || simulation === void 0 ? void 0 : simulation.value.err) === instructionError ||
41
+ JSON.stringify(simulation === null || simulation === void 0 ? void 0 : simulation.value.err) === insufficientFundsForRent) {
42
+ throw new Error('Insufficient funds');
43
+ }
44
+ return undefined;
45
+ }
46
+ const totalSolTransfer = previousBalance - ((_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[0]) === null || _f === void 0 ? void 0 : _f.lamports);
47
+ return BigInt(totalSolTransfer);
48
+ });
11
49
  const decodeTransaction = (transaction, connection, thisAddress) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
12
- var _a;
50
+ var _g;
13
51
  if (!transaction) {
14
52
  throw new utils.DynamicError('Transaction is required');
15
53
  }
16
- let decodedInstructions = [];
17
- if ('version' in transaction) {
18
- const lookupTableAddresses = transaction.message.addressTableLookups.map((lookup) => new web3_js.PublicKey(lookup.accountKey));
19
- // for NON simple sol transfers we need to fetch the lookup table accounts
20
- if (lookupTableAddresses.length > 0) {
21
- const lookupTables = yield Promise.all(lookupTableAddresses.map((address) => connection.getAddressLookupTable(address)));
22
- const lookupTableAccounts = lookupTables
23
- .filter((result) => result !== null)
24
- .map((result) => result.value);
25
- if (lookupTableAccounts.length > 0) {
26
- decodedInstructions = web3_js.TransactionMessage.decompile(transaction.message, {
27
- addressLookupTableAccounts: lookupTableAccounts,
28
- }).instructions;
54
+ try {
55
+ let decodedInstructions = [];
56
+ if ('version' in transaction) {
57
+ const lookupTableAddresses = transaction.message.addressTableLookups.map((lookup) => new web3_js.PublicKey(lookup.accountKey));
58
+ // For non-simple SOL transfers, we need to fetch the lookup table accounts
59
+ if (lookupTableAddresses.length > 0) {
60
+ const lookupTables = yield Promise.all(lookupTableAddresses.map((address) => connection.getAddressLookupTable(address)));
61
+ const lookupTableAccounts = lookupTables
62
+ .filter((result) => result !== null)
63
+ .map((result) => result.value);
64
+ if (lookupTableAccounts.length > 0) {
65
+ decodedInstructions = web3_js.TransactionMessage.decompile(transaction.message, {
66
+ addressLookupTableAccounts: lookupTableAccounts,
67
+ }).instructions;
68
+ }
29
69
  }
70
+ else {
71
+ decodedInstructions = web3_js.TransactionMessage.decompile(transaction.message).instructions;
72
+ }
73
+ }
74
+ else if (!transaction.instructions) {
75
+ decodedInstructions = (_g = web3_js.Transaction.from(Buffer.from(transaction.serialize()))) === null || _g === void 0 ? void 0 : _g.instructions;
30
76
  }
31
77
  else {
32
- decodedInstructions = web3_js.TransactionMessage.decompile(transaction.message).instructions;
78
+ decodedInstructions = transaction.instructions;
33
79
  }
34
- }
35
- else if (!transaction.instructions) {
36
- decodedInstructions = (_a = web3_js.Transaction.from(Buffer.from(transaction.serialize()))) === null || _a === void 0 ? void 0 : _a.instructions;
37
- }
38
- else {
39
- decodedInstructions = transaction.instructions;
40
- }
41
- if (!(decodedInstructions === null || decodedInstructions === void 0 ? void 0 : decodedInstructions.length)) {
42
- throw new utils.DynamicError('Bad formatted instruction');
43
- }
44
- const solTransfers = decodedInstructions.filter((instruction) => instruction.programId.equals(web3_js.SystemProgram.programId));
45
- // non SPL transfers, just SOL
46
- if (solTransfers.length > 0) {
47
- return solTransfers.map((decodedInstruction) => {
48
- const decodedTransferInstruction = web3_js.SystemInstruction.decodeTransfer(decodedInstruction);
49
- return {
50
- from: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.fromPubkey.toBase58(),
51
- to: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.toPubkey.toBase58(),
52
- value: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.lamports,
53
- };
54
- });
55
- }
56
- // SPL transfers
57
- return Promise.all(decodedInstructions.map((instruction) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
58
- var _b, _c, _d, _e, _f, _g, _h;
59
- if (instruction.programId.equals(splToken.TOKEN_PROGRAM_ID)) {
60
- const decodedTokenInstruction = splToken.decodeTransferInstructionUnchecked(instruction);
61
- const { source, destination } = decodedTokenInstruction.keys;
62
- if (destination) {
63
- // for contract interactions, ex. swaps, the destination is the turnkey address, flip sender and receiver
64
- if ((destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58()) === thisAddress) {
80
+ if (!(decodedInstructions === null || decodedInstructions === void 0 ? void 0 : decodedInstructions.length)) {
81
+ throw new utils.DynamicError('Bad formatted instruction');
82
+ }
83
+ const solTransfers = decodedInstructions.filter((instruction) => instruction.programId.equals(web3_js.SystemProgram.programId));
84
+ // Non-SPL transfers, just SOL
85
+ if (solTransfers.length > 0) {
86
+ return solTransfers.map((decodedInstruction) => {
87
+ let decodedTransferInstruction;
88
+ try {
89
+ decodedTransferInstruction =
90
+ web3_js.SystemInstruction.decodeTransfer(decodedInstruction);
91
+ }
92
+ catch (e) {
93
+ return { from: thisAddress, to: 'Unknown' };
94
+ }
95
+ return {
96
+ from: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.fromPubkey.toBase58(),
97
+ to: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.toPubkey.toBase58(),
98
+ };
99
+ });
100
+ }
101
+ // SPL transfers
102
+ let splTransfers = yield Promise.all(decodedInstructions.map((instruction) => _tslib.__awaiter(void 0, void 0, void 0, function* () {
103
+ var _h, _j, _k, _l, _m, _o, _p;
104
+ if (instruction.programId.equals(splToken.TOKEN_PROGRAM_ID)) {
105
+ const decodedTokenInstruction = splToken.decodeTransferInstructionUnchecked(instruction);
106
+ const { source, destination } = decodedTokenInstruction.keys;
107
+ if (destination) {
108
+ // For contract interactions, e.g., swaps, the destination is the turnkey address, flip sender and receiver
109
+ if ((destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58()) === thisAddress) {
110
+ return {
111
+ from: thisAddress,
112
+ to: source === null || source === void 0 ? void 0 : source.pubkey.toBase58(),
113
+ };
114
+ }
115
+ // Pure SPL transfers, get the address from the destination token account to display to user
116
+ const destinationAccountInfo = yield connection.getParsedAccountInfo(destination.pubkey);
117
+ const isTokenAccount = ((_k = (_j = (_h = destinationAccountInfo.value) === null || _h === void 0 ? void 0 : _h.data) === null || _j === void 0 ? void 0 : _j.parsed) === null || _k === void 0 ? void 0 : _k.type) === 'account';
118
+ const destinationOwner = isTokenAccount
119
+ ? (_p = (_o = (_m = (_l = destinationAccountInfo.value) === null || _l === void 0 ? void 0 : _l.data) === null || _m === void 0 ? void 0 : _m.parsed) === null || _o === void 0 ? void 0 : _o.info) === null || _p === void 0 ? void 0 : _p.owner
120
+ : null;
121
+ const toAddress = destinationOwner
122
+ ? destinationOwner
123
+ : destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58();
65
124
  return {
66
125
  from: thisAddress,
67
- to: source === null || source === void 0 ? void 0 : source.pubkey.toBase58(),
68
- value: decodedTokenInstruction.data.amount,
126
+ to: toAddress,
69
127
  };
70
128
  }
71
- // Pure SPL transfers, get the address from the destination token account to display to user
72
- const destinationAccountInfo = yield connection.getParsedAccountInfo(destination.pubkey);
73
- const isTokenAccount = ((_d = (_c = (_b = destinationAccountInfo.value) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.parsed) === null || _d === void 0 ? void 0 : _d.type) === 'account';
74
- const destinationOwner = isTokenAccount
75
- ? (_h = (_g = (_f = (_e = destinationAccountInfo.value) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.parsed) === null || _g === void 0 ? void 0 : _g.info) === null || _h === void 0 ? void 0 : _h.owner
76
- : null;
77
- const toAddress = destinationOwner
78
- ? destinationOwner
79
- : destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58();
80
- return {
81
- from: thisAddress,
82
- to: toAddress,
83
- value: BigInt(0),
84
- };
85
129
  }
86
- }
87
- return null;
88
- })));
130
+ return null;
131
+ })));
132
+ splTransfers = splTransfers.filter((transfer) => transfer !== null);
133
+ if (splTransfers === null || splTransfers === void 0 ? void 0 : splTransfers.length)
134
+ return splTransfers;
135
+ // Return program IDs for non-SOL and non-SPL transfers
136
+ const noTransferDestinations = decodedInstructions.map((instruction) => ({
137
+ from: thisAddress,
138
+ to: instruction.programId.toBase58(),
139
+ }));
140
+ if (noTransferDestinations.length)
141
+ return noTransferDestinations;
142
+ return [{ from: thisAddress, to: 'Unknown' }];
143
+ }
144
+ catch (error) {
145
+ walletConnectorCore.logger.warn('[decodeTransaction]', error);
146
+ return [{ from: thisAddress, to: 'Unknown' }];
147
+ }
89
148
  });
90
149
  const summarizeTransactionDecodedData = (transactionsData) => {
91
150
  const recipients = new Set();
92
- let transferTotalValue = BigInt(0);
93
151
  transactionsData.forEach((transactionData) => {
94
152
  if (transactionData && transactionData.to) {
95
153
  recipients.add(transactionData.to);
96
- transferTotalValue += transactionData.value;
97
154
  }
98
155
  });
99
- const to = recipients.size === 1
100
- ? recipients.values().next().value
101
- : 'dyn_send_transaction.multiple_recipients';
102
- return { to, value: transferTotalValue };
156
+ const to = recipients.size === 1 ? recipients.values().next().value : 'Multiple';
157
+ return to;
103
158
  };
104
159
 
105
160
  exports.decodeTransaction = decodeTransaction;
161
+ exports.getTotalSolanaSpend = getTotalSolanaSpend;
106
162
  exports.summarizeTransactionDecodedData = summarizeTransactionDecodedData;
@@ -1,10 +1,12 @@
1
1
  import { Transaction, VersionedTransaction, Connection } from '@solana/web3.js';
2
- export declare const decodeTransaction: (transaction: Transaction | VersionedTransaction, connection: Connection, thisAddress: string) => Promise<any>;
3
- export declare const summarizeTransactionDecodedData: (transactionsData: {
2
+ type DestinationAndFrom = {
4
3
  to: string;
5
4
  from: string;
6
- value: bigint;
7
- }[]) => {
8
- to: any;
9
- value: bigint;
10
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 {};
@@ -2,100 +2,155 @@
2
2
  import { __awaiter } from '../../../../_virtual/_tslib.js';
3
3
  import { PublicKey, TransactionMessage, Transaction, SystemProgram, SystemInstruction } from '@solana/web3.js';
4
4
  import { TOKEN_PROGRAM_ID, decodeTransferInstructionUnchecked } from '@solana/spl-token';
5
+ import { logger } from '@dynamic-labs/wallet-connector-core';
5
6
  import { DynamicError } from '@dynamic-labs/utils';
6
7
 
8
+ const getTotalSolanaSpend = (transaction, connection, thisAddress) => __awaiter(void 0, void 0, void 0, function* () {
9
+ var _a, _b, _c, _d, _e, _f;
10
+ let simulation;
11
+ if ('version' in transaction) {
12
+ simulation = yield connection.simulateTransaction(transaction, {
13
+ accounts: { addresses: [thisAddress], encoding: 'base64' },
14
+ replaceRecentBlockhash: true,
15
+ });
16
+ }
17
+ else {
18
+ simulation = yield connection.simulateTransaction(transaction, undefined, [new PublicKey(thisAddress)]);
19
+ }
20
+ const previousBalance = yield connection.getBalance(new PublicKey(thisAddress));
21
+ 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)) {
22
+ logger.debug('Transaction simulation failed', simulation);
23
+ const instructionError = JSON.stringify({
24
+ InstructionError: [
25
+ 0,
26
+ {
27
+ Custom: 1,
28
+ },
29
+ ],
30
+ });
31
+ const insufficientFundsForRent = JSON.stringify({
32
+ InsufficientFundsForRent: {
33
+ account_index: 0,
34
+ },
35
+ });
36
+ if (JSON.stringify(simulation === null || simulation === void 0 ? void 0 : simulation.value.err) === instructionError ||
37
+ JSON.stringify(simulation === null || simulation === void 0 ? void 0 : simulation.value.err) === insufficientFundsForRent) {
38
+ throw new Error('Insufficient funds');
39
+ }
40
+ return undefined;
41
+ }
42
+ const totalSolTransfer = previousBalance - ((_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[0]) === null || _f === void 0 ? void 0 : _f.lamports);
43
+ return BigInt(totalSolTransfer);
44
+ });
7
45
  const decodeTransaction = (transaction, connection, thisAddress) => __awaiter(void 0, void 0, void 0, function* () {
8
- var _a;
46
+ var _g;
9
47
  if (!transaction) {
10
48
  throw new DynamicError('Transaction is required');
11
49
  }
12
- let decodedInstructions = [];
13
- if ('version' in transaction) {
14
- const lookupTableAddresses = transaction.message.addressTableLookups.map((lookup) => new PublicKey(lookup.accountKey));
15
- // for NON simple sol transfers we need to fetch the lookup table accounts
16
- if (lookupTableAddresses.length > 0) {
17
- const lookupTables = yield Promise.all(lookupTableAddresses.map((address) => connection.getAddressLookupTable(address)));
18
- const lookupTableAccounts = lookupTables
19
- .filter((result) => result !== null)
20
- .map((result) => result.value);
21
- if (lookupTableAccounts.length > 0) {
22
- decodedInstructions = TransactionMessage.decompile(transaction.message, {
23
- addressLookupTableAccounts: lookupTableAccounts,
24
- }).instructions;
50
+ try {
51
+ let decodedInstructions = [];
52
+ if ('version' in transaction) {
53
+ const lookupTableAddresses = transaction.message.addressTableLookups.map((lookup) => new PublicKey(lookup.accountKey));
54
+ // For non-simple SOL transfers, we need to fetch the lookup table accounts
55
+ if (lookupTableAddresses.length > 0) {
56
+ const lookupTables = yield Promise.all(lookupTableAddresses.map((address) => connection.getAddressLookupTable(address)));
57
+ const lookupTableAccounts = lookupTables
58
+ .filter((result) => result !== null)
59
+ .map((result) => result.value);
60
+ if (lookupTableAccounts.length > 0) {
61
+ decodedInstructions = TransactionMessage.decompile(transaction.message, {
62
+ addressLookupTableAccounts: lookupTableAccounts,
63
+ }).instructions;
64
+ }
25
65
  }
66
+ else {
67
+ decodedInstructions = TransactionMessage.decompile(transaction.message).instructions;
68
+ }
69
+ }
70
+ else if (!transaction.instructions) {
71
+ decodedInstructions = (_g = Transaction.from(Buffer.from(transaction.serialize()))) === null || _g === void 0 ? void 0 : _g.instructions;
26
72
  }
27
73
  else {
28
- decodedInstructions = TransactionMessage.decompile(transaction.message).instructions;
74
+ decodedInstructions = transaction.instructions;
29
75
  }
30
- }
31
- else if (!transaction.instructions) {
32
- decodedInstructions = (_a = Transaction.from(Buffer.from(transaction.serialize()))) === null || _a === void 0 ? void 0 : _a.instructions;
33
- }
34
- else {
35
- decodedInstructions = transaction.instructions;
36
- }
37
- if (!(decodedInstructions === null || decodedInstructions === void 0 ? void 0 : decodedInstructions.length)) {
38
- throw new DynamicError('Bad formatted instruction');
39
- }
40
- const solTransfers = decodedInstructions.filter((instruction) => instruction.programId.equals(SystemProgram.programId));
41
- // non SPL transfers, just SOL
42
- if (solTransfers.length > 0) {
43
- return solTransfers.map((decodedInstruction) => {
44
- const decodedTransferInstruction = SystemInstruction.decodeTransfer(decodedInstruction);
45
- return {
46
- from: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.fromPubkey.toBase58(),
47
- to: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.toPubkey.toBase58(),
48
- value: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.lamports,
49
- };
50
- });
51
- }
52
- // SPL transfers
53
- return Promise.all(decodedInstructions.map((instruction) => __awaiter(void 0, void 0, void 0, function* () {
54
- var _b, _c, _d, _e, _f, _g, _h;
55
- if (instruction.programId.equals(TOKEN_PROGRAM_ID)) {
56
- const decodedTokenInstruction = decodeTransferInstructionUnchecked(instruction);
57
- const { source, destination } = decodedTokenInstruction.keys;
58
- if (destination) {
59
- // for contract interactions, ex. swaps, the destination is the turnkey address, flip sender and receiver
60
- if ((destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58()) === thisAddress) {
76
+ if (!(decodedInstructions === null || decodedInstructions === void 0 ? void 0 : decodedInstructions.length)) {
77
+ throw new DynamicError('Bad formatted instruction');
78
+ }
79
+ const solTransfers = decodedInstructions.filter((instruction) => instruction.programId.equals(SystemProgram.programId));
80
+ // Non-SPL transfers, just SOL
81
+ if (solTransfers.length > 0) {
82
+ return solTransfers.map((decodedInstruction) => {
83
+ let decodedTransferInstruction;
84
+ try {
85
+ decodedTransferInstruction =
86
+ SystemInstruction.decodeTransfer(decodedInstruction);
87
+ }
88
+ catch (e) {
89
+ return { from: thisAddress, to: 'Unknown' };
90
+ }
91
+ return {
92
+ from: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.fromPubkey.toBase58(),
93
+ to: decodedTransferInstruction === null || decodedTransferInstruction === void 0 ? void 0 : decodedTransferInstruction.toPubkey.toBase58(),
94
+ };
95
+ });
96
+ }
97
+ // SPL transfers
98
+ let splTransfers = yield Promise.all(decodedInstructions.map((instruction) => __awaiter(void 0, void 0, void 0, function* () {
99
+ var _h, _j, _k, _l, _m, _o, _p;
100
+ if (instruction.programId.equals(TOKEN_PROGRAM_ID)) {
101
+ const decodedTokenInstruction = decodeTransferInstructionUnchecked(instruction);
102
+ const { source, destination } = decodedTokenInstruction.keys;
103
+ if (destination) {
104
+ // For contract interactions, e.g., swaps, the destination is the turnkey address, flip sender and receiver
105
+ if ((destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58()) === thisAddress) {
106
+ return {
107
+ from: thisAddress,
108
+ to: source === null || source === void 0 ? void 0 : source.pubkey.toBase58(),
109
+ };
110
+ }
111
+ // Pure SPL transfers, get the address from the destination token account to display to user
112
+ const destinationAccountInfo = yield connection.getParsedAccountInfo(destination.pubkey);
113
+ const isTokenAccount = ((_k = (_j = (_h = destinationAccountInfo.value) === null || _h === void 0 ? void 0 : _h.data) === null || _j === void 0 ? void 0 : _j.parsed) === null || _k === void 0 ? void 0 : _k.type) === 'account';
114
+ const destinationOwner = isTokenAccount
115
+ ? (_p = (_o = (_m = (_l = destinationAccountInfo.value) === null || _l === void 0 ? void 0 : _l.data) === null || _m === void 0 ? void 0 : _m.parsed) === null || _o === void 0 ? void 0 : _o.info) === null || _p === void 0 ? void 0 : _p.owner
116
+ : null;
117
+ const toAddress = destinationOwner
118
+ ? destinationOwner
119
+ : destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58();
61
120
  return {
62
121
  from: thisAddress,
63
- to: source === null || source === void 0 ? void 0 : source.pubkey.toBase58(),
64
- value: decodedTokenInstruction.data.amount,
122
+ to: toAddress,
65
123
  };
66
124
  }
67
- // Pure SPL transfers, get the address from the destination token account to display to user
68
- const destinationAccountInfo = yield connection.getParsedAccountInfo(destination.pubkey);
69
- const isTokenAccount = ((_d = (_c = (_b = destinationAccountInfo.value) === null || _b === void 0 ? void 0 : _b.data) === null || _c === void 0 ? void 0 : _c.parsed) === null || _d === void 0 ? void 0 : _d.type) === 'account';
70
- const destinationOwner = isTokenAccount
71
- ? (_h = (_g = (_f = (_e = destinationAccountInfo.value) === null || _e === void 0 ? void 0 : _e.data) === null || _f === void 0 ? void 0 : _f.parsed) === null || _g === void 0 ? void 0 : _g.info) === null || _h === void 0 ? void 0 : _h.owner
72
- : null;
73
- const toAddress = destinationOwner
74
- ? destinationOwner
75
- : destination === null || destination === void 0 ? void 0 : destination.pubkey.toBase58();
76
- return {
77
- from: thisAddress,
78
- to: toAddress,
79
- value: BigInt(0),
80
- };
81
125
  }
82
- }
83
- return null;
84
- })));
126
+ return null;
127
+ })));
128
+ splTransfers = splTransfers.filter((transfer) => transfer !== null);
129
+ if (splTransfers === null || splTransfers === void 0 ? void 0 : splTransfers.length)
130
+ return splTransfers;
131
+ // Return program IDs for non-SOL and non-SPL transfers
132
+ const noTransferDestinations = decodedInstructions.map((instruction) => ({
133
+ from: thisAddress,
134
+ to: instruction.programId.toBase58(),
135
+ }));
136
+ if (noTransferDestinations.length)
137
+ return noTransferDestinations;
138
+ return [{ from: thisAddress, to: 'Unknown' }];
139
+ }
140
+ catch (error) {
141
+ logger.warn('[decodeTransaction]', error);
142
+ return [{ from: thisAddress, to: 'Unknown' }];
143
+ }
85
144
  });
86
145
  const summarizeTransactionDecodedData = (transactionsData) => {
87
146
  const recipients = new Set();
88
- let transferTotalValue = BigInt(0);
89
147
  transactionsData.forEach((transactionData) => {
90
148
  if (transactionData && transactionData.to) {
91
149
  recipients.add(transactionData.to);
92
- transferTotalValue += transactionData.value;
93
150
  }
94
151
  });
95
- const to = recipients.size === 1
96
- ? recipients.values().next().value
97
- : 'dyn_send_transaction.multiple_recipients';
98
- return { to, value: transferTotalValue };
152
+ const to = recipients.size === 1 ? recipients.values().next().value : 'Multiple';
153
+ return to;
99
154
  };
100
155
 
101
- export { decodeTransaction, summarizeTransactionDecodedData };
156
+ export { decodeTransaction, getTotalSolanaSpend, summarizeTransactionDecodedData };
@@ -1,8 +0,0 @@
1
- 'use client'
2
- 'use strict';
3
-
4
- Object.defineProperty(exports, '__esModule', { value: true });
5
-
6
- const SOLANA_GENESIS_HASH = 'genesis-hash';
7
-
8
- exports.SOLANA_GENESIS_HASH = SOLANA_GENESIS_HASH;
@@ -1 +0,0 @@
1
- export declare const SOLANA_GENESIS_HASH = "genesis-hash";
@@ -1,4 +0,0 @@
1
- 'use client'
2
- const SOLANA_GENESIS_HASH = 'genesis-hash';
3
-
4
- export { SOLANA_GENESIS_HASH };