@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.
- package/CHANGELOG.md +628 -0
- package/package.cjs +22 -0
- package/package.js +17 -0
- package/package.json +15 -12
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.cjs +4 -7
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.d.ts +6 -5
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaSigner.js +4 -7
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.cjs +138 -39
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.d.ts +16 -11
- package/src/lib/TurnkeySolanaWalletConnector/TurnkeySolanaWalletConnector.js +136 -37
- package/src/lib/utils/api/api.cjs +38 -0
- package/src/lib/utils/api/api.d.ts +4 -0
- package/src/lib/utils/api/api.js +32 -0
- package/src/lib/utils/api/events/DynamicEvents.d.ts +6 -0
- package/src/lib/utils/api/events/auth.d.ts +49 -0
- package/src/lib/utils/api/utils/ApiEndpoint.cjs +41 -0
- package/src/lib/utils/api/utils/ApiEndpoint.d.ts +7 -0
- package/src/lib/utils/api/utils/ApiEndpoint.js +39 -0
- package/src/lib/utils/api/utils/SdkApi.cjs +35 -0
- package/src/lib/utils/api/utils/SdkApi.d.ts +2 -0
- package/src/lib/utils/api/utils/SdkApi.js +31 -0
- package/src/lib/utils/api/utils/helpers.cjs +92 -0
- package/src/lib/utils/api/utils/helpers.d.ts +12 -0
- package/src/lib/utils/api/utils/helpers.js +81 -0
- package/src/lib/utils/api/utils/version.cjs +12 -0
- package/src/lib/utils/api/utils/version.d.ts +2 -0
- package/src/lib/utils/api/utils/version.js +7 -0
- package/src/lib/utils/index.d.ts +1 -2
- package/src/lib/utils/transactionDecoder/index.d.ts +1 -1
- package/src/lib/utils/transactionDecoder/transactionDecoder.cjs +127 -71
- package/src/lib/utils/transactionDecoder/transactionDecoder.d.ts +8 -6
- package/src/lib/utils/transactionDecoder/transactionDecoder.js +127 -72
- package/src/lib/constants.cjs +0 -8
- package/src/lib/constants.d.ts +0 -1
- package/src/lib/constants.js +0 -4
- package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.cjs +0 -10
- package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.d.ts +0 -1
- package/src/lib/utils/getGenesisHashLSKey/getGenesisHashLSKey.js +0 -6
- 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;
|
package/src/lib/utils/index.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
1
|
export { createSolanaConnection } from './createSolanaConnection';
|
|
2
|
-
export {
|
|
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
|
|
50
|
+
var _g;
|
|
13
51
|
if (!transaction) {
|
|
14
52
|
throw new utils.DynamicError('Transaction is required');
|
|
15
53
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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 =
|
|
78
|
+
decodedInstructions = transaction.instructions;
|
|
33
79
|
}
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
46
|
+
var _g;
|
|
9
47
|
if (!transaction) {
|
|
10
48
|
throw new DynamicError('Transaction is required');
|
|
11
49
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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 =
|
|
74
|
+
decodedInstructions = transaction.instructions;
|
|
29
75
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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 };
|
package/src/lib/constants.cjs
DELETED
package/src/lib/constants.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const SOLANA_GENESIS_HASH = "genesis-hash";
|
package/src/lib/constants.js
DELETED