@exodus/solana-lib 3.11.2 → 3.12.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 +24 -0
- package/package.json +4 -4
- package/src/helpers/spl-token-2022.js +8 -3
- package/src/helpers/tokenTransfer.js +1 -1
- package/src/key-identifier.js +1 -0
- package/src/msg/sign-message.js +2 -2
- package/src/transaction.js +13 -25
- package/src/tx/create-unsigned-tx.js +2 -3
- package/src/tx/prepare-for-signing.js +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,30 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [3.12.1](https://github.com/ExodusMovement/assets/compare/@exodus/solana-lib@3.12.0...@exodus/solana-lib@3.12.1) (2025-09-29)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @exodus/solana-lib
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [3.12.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-lib@3.11.2...@exodus/solana-lib@3.12.0) (2025-09-25)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Features
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
* feat: use trezor compatibility mode for solana (#6564)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Bug Fixes
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
* fix: don't use Sync methods in async (#5682)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
6
30
|
## [3.11.2](https://github.com/ExodusMovement/assets/compare/@exodus/solana-lib@3.11.1...@exodus/solana-lib@3.11.2) (2025-05-05)
|
|
7
31
|
|
|
8
32
|
**Note:** Version bump only for package @exodus/solana-lib
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-lib",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.1",
|
|
4
4
|
"description": "Solana utils, such as for cryptography, address encoding/decoding, transaction building, etc.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"minimalistic-assert": "^1.0.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
+
"@exodus/bip39": "^1.0.1",
|
|
36
37
|
"@exodus/key-identifier": "^1.3.0",
|
|
37
38
|
"@exodus/keychain": "^7.3.0",
|
|
38
|
-
"@exodus/solana-meta": "^2.0.0"
|
|
39
|
-
"bip39": "^2.6.0"
|
|
39
|
+
"@exodus/solana-meta": "^2.0.0"
|
|
40
40
|
},
|
|
41
41
|
"bugs": {
|
|
42
42
|
"url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Asolana-lib"
|
|
@@ -46,5 +46,5 @@
|
|
|
46
46
|
"type": "git",
|
|
47
47
|
"url": "git+https://github.com/ExodusMovement/assets.git"
|
|
48
48
|
},
|
|
49
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "bdbe86b58adda62d0ea7ef8cc8d4c633d3bd32be"
|
|
50
50
|
}
|
|
@@ -118,10 +118,13 @@ export function decodeTransferCheckedWithFeeInstruction(
|
|
|
118
118
|
instruction, // TransactionInstruction
|
|
119
119
|
programId // PublicKey
|
|
120
120
|
) {
|
|
121
|
-
if (!instruction.programId.equals(programId))
|
|
121
|
+
if (!instruction.programId.equals(programId)) {
|
|
122
122
|
throw new Error('TokenInvalidInstructionProgramError')
|
|
123
|
-
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (instruction.data.length !== transferCheckedWithFeeInstructionData.span) {
|
|
124
126
|
throw new Error('TokenInvalidInstructionDataError')
|
|
127
|
+
}
|
|
125
128
|
|
|
126
129
|
const {
|
|
127
130
|
keys: { source, mint, destination, authority, signers },
|
|
@@ -130,8 +133,10 @@ export function decodeTransferCheckedWithFeeInstruction(
|
|
|
130
133
|
if (
|
|
131
134
|
data.instruction !== TokenInstruction.TransferFeeExtension ||
|
|
132
135
|
data.transferFeeInstruction !== TransferFeeInstruction.TransferCheckedWithFee
|
|
133
|
-
)
|
|
136
|
+
) {
|
|
134
137
|
throw new Error('TokenInvalidInstructionTypeError')
|
|
138
|
+
}
|
|
139
|
+
|
|
135
140
|
if (!mint) throw new Error('TokenInvalidInstructionKeysError')
|
|
136
141
|
|
|
137
142
|
return {
|
package/src/key-identifier.js
CHANGED
package/src/msg/sign-message.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { signDetached } from '@exodus/crypto/curve25519'
|
|
2
2
|
import assert from 'minimalistic-assert'
|
|
3
3
|
|
|
4
4
|
import { assertValidMessage } from './validation.js'
|
|
@@ -11,5 +11,5 @@ export const signMessageNew = async ({ privateKey, message }) => {
|
|
|
11
11
|
`privateKey is not a Buffer or Uint8Array`
|
|
12
12
|
)
|
|
13
13
|
|
|
14
|
-
return
|
|
14
|
+
return signDetached({ message: rawMessage, privateKey, format: 'buffer' })
|
|
15
15
|
}
|
package/src/transaction.js
CHANGED
|
@@ -30,7 +30,6 @@ class Tx {
|
|
|
30
30
|
to,
|
|
31
31
|
amount,
|
|
32
32
|
recentBlockhash,
|
|
33
|
-
fee, // (Fee per Signature: 5000 lamports)
|
|
34
33
|
// Tokens related:
|
|
35
34
|
// pass either name or mintAddress, if both, mintAddress has priority
|
|
36
35
|
tokenMintAddress,
|
|
@@ -48,7 +47,7 @@ class Tx {
|
|
|
48
47
|
assert(from, 'from is required')
|
|
49
48
|
assert(to, 'to is required')
|
|
50
49
|
assert(amount, 'amount is required')
|
|
51
|
-
assert(typeof amount === '
|
|
50
|
+
assert(typeof amount === 'string', 'amount must be a string')
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
assert(recentBlockhash, 'recentBlockhash is required')
|
|
@@ -105,7 +104,7 @@ class Tx {
|
|
|
105
104
|
const txInstruction = SystemProgram.transfer({
|
|
106
105
|
fromPubkey: new PublicKey(from),
|
|
107
106
|
toPubkey: new PublicKey(to),
|
|
108
|
-
lamports: amount,
|
|
107
|
+
lamports: new BN(amount),
|
|
109
108
|
})
|
|
110
109
|
|
|
111
110
|
// If reference accounts are provided, add them to the transfer instruction
|
|
@@ -167,35 +166,29 @@ class Tx {
|
|
|
167
166
|
if (!rawTokenProgram) throw new Error('Cannot detect token program')
|
|
168
167
|
const tokenProgram = new PublicKey(rawTokenProgram).toBase58()
|
|
169
168
|
// crete account instruction
|
|
170
|
-
if (isSOLaddress && !isAssociatedTokenAccountActive)
|
|
169
|
+
if (isSOLaddress && !isAssociatedTokenAccountActive) {
|
|
171
170
|
this.transaction.add(createAssociatedTokenAccount(from, tokenMintAddress, to, tokenProgram))
|
|
171
|
+
}
|
|
172
172
|
|
|
173
|
-
let amountLeft = amount
|
|
173
|
+
let amountLeft = new BN(amount)
|
|
174
174
|
let amountToSend
|
|
175
175
|
let isNotEnoughBalance = false
|
|
176
|
-
for (let {
|
|
177
|
-
mintAddress,
|
|
178
|
-
tokenAccountAddress,
|
|
179
|
-
balance,
|
|
180
|
-
decimals,
|
|
181
|
-
feeBasisPoints,
|
|
182
|
-
maximumFee,
|
|
183
|
-
} of fromTokenAddresses) {
|
|
176
|
+
for (let { mintAddress, tokenAccountAddress, balance, decimals } of fromTokenAddresses) {
|
|
184
177
|
// need to add more of this instruction until we reach the desired balance (amount) to send
|
|
185
178
|
assert(mintAddress === tokenMintAddress, `Got unexpected mintAddress ${mintAddress}`)
|
|
186
179
|
|
|
187
180
|
if (checkBalances) {
|
|
188
|
-
if (amountLeft
|
|
181
|
+
if (amountLeft.isZero()) break
|
|
189
182
|
|
|
190
|
-
balance =
|
|
191
|
-
if (balance
|
|
183
|
+
balance = new BN(balance)
|
|
184
|
+
if (balance.gte(amountLeft)) {
|
|
192
185
|
amountToSend = amountLeft
|
|
193
|
-
amountLeft = 0
|
|
186
|
+
amountLeft = new BN(0)
|
|
194
187
|
} else {
|
|
195
188
|
// Not enough balance case.
|
|
196
189
|
isNotEnoughBalance = true
|
|
197
190
|
amountToSend = balance
|
|
198
|
-
amountLeft
|
|
191
|
+
amountLeft = amountLeft.sub(amountToSend)
|
|
199
192
|
}
|
|
200
193
|
} else {
|
|
201
194
|
amountToSend = amountLeft
|
|
@@ -206,18 +199,13 @@ class Tx {
|
|
|
206
199
|
: to
|
|
207
200
|
let tokenTransferInstruction
|
|
208
201
|
if (tokenProgram === TOKEN_2022_PROGRAM_ID.toBase58()) {
|
|
209
|
-
// token transfer fee
|
|
210
|
-
const fee = Math.ceil((amountToSend * feeBasisPoints) / 10_000)
|
|
211
|
-
const feeCharged = fee > maximumFee ? maximumFee : fee
|
|
212
|
-
|
|
213
202
|
tokenTransferInstruction = createTransferCheckedWithFeeInstruction(
|
|
214
203
|
tokenAccountAddress,
|
|
215
204
|
tokenMintAddress,
|
|
216
205
|
dest,
|
|
217
206
|
from,
|
|
218
207
|
amountToSend,
|
|
219
|
-
decimals
|
|
220
|
-
feeCharged // token fee (not SOL fee)
|
|
208
|
+
decimals // token decimals
|
|
221
209
|
)
|
|
222
210
|
} else {
|
|
223
211
|
tokenTransferInstruction = createTokenTransferInstruction(
|
|
@@ -263,7 +251,7 @@ class Tx {
|
|
|
263
251
|
seed,
|
|
264
252
|
authorized,
|
|
265
253
|
lockup,
|
|
266
|
-
lamports: amount,
|
|
254
|
+
lamports: new BN(amount),
|
|
267
255
|
})
|
|
268
256
|
|
|
269
257
|
// delegate funds instruction
|
|
@@ -41,9 +41,8 @@ export function createUnsignedTx({
|
|
|
41
41
|
txData: {
|
|
42
42
|
from,
|
|
43
43
|
to,
|
|
44
|
-
amount: amount ? amount.
|
|
45
|
-
fee: fee ? fee.
|
|
46
|
-
fixedFee: feeData ? feeData.fee.toBaseNumber() : null,
|
|
44
|
+
amount: amount ? amount.toBaseString() : null,
|
|
45
|
+
fee: fee ? fee.toBaseString() : null,
|
|
47
46
|
recentBlockhash,
|
|
48
47
|
// Tokens related:
|
|
49
48
|
tokenMintAddress,
|
|
@@ -50,7 +50,7 @@ export function prepareForSigning(unsignedTx, { checkBalances = true } = {}) {
|
|
|
50
50
|
const address = from
|
|
51
51
|
|
|
52
52
|
const amount = unitAmount
|
|
53
|
-
? new BN(isNumberUnit(unitAmount) ? unitAmount.toBaseString() : unitAmount).
|
|
53
|
+
? new BN(isNumberUnit(unitAmount) ? unitAmount.toBaseString() : unitAmount).toString()
|
|
54
54
|
: unitAmount
|
|
55
55
|
|
|
56
56
|
const fee = feeAmount
|