@exodus/solana-api 3.26.3 → 3.26.5

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
@@ -3,6 +3,24 @@
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.26.5](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.26.4...@exodus/solana-api@3.26.5) (2025-12-29)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix: solana fee handling in createTxFactory (#7185)
13
+
14
+
15
+
16
+ ## [3.26.4](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.26.3...@exodus/solana-api@3.26.4) (2025-12-27)
17
+
18
+ **Note:** Version bump only for package @exodus/solana-api
19
+
20
+
21
+
22
+
23
+
6
24
  ## [3.26.3](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.26.2...@exodus/solana-api@3.26.3) (2025-12-19)
7
25
 
8
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/solana-api",
3
- "version": "3.26.3",
3
+ "version": "3.26.5",
4
4
  "description": "Transaction monitors, fee monitors, RPC with the blockchain node, and other networking code for Solana",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -49,7 +49,7 @@
49
49
  "@exodus/assets-testing": "^1.0.0",
50
50
  "@exodus/solana-web3.js": "^1.63.1-exodus.9-rc3"
51
51
  },
52
- "gitHead": "ae424af3e4254f05509527496806913d56e39aca",
52
+ "gitHead": "1d62bfbf0924dc4c6eb52f6af2417c220f7454cb",
53
53
  "bugs": {
54
54
  "url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Asolana-api"
55
55
  },
@@ -223,7 +223,7 @@ export const createTxFactory = ({ assetClientInterface, api, feePayerClient }) =
223
223
  )
224
224
  }
225
225
 
226
- const fee = feeData.baseFee
226
+ const calculatedFee = feeData.baseFee
227
227
  .add(
228
228
  asset.feeAsset.currency
229
229
  .baseUnit(unsignedTx.txData.priorityFee ?? 0)
@@ -232,32 +232,34 @@ export const createTxFactory = ({ assetClientInterface, api, feePayerClient }) =
232
232
  )
233
233
  .add(tokenCreationFee)
234
234
 
235
- unsignedTx.txMeta.fee = fee.toBaseNumber()
236
-
237
235
  const tx = await maybeAddFeePayerWithAuth({
238
236
  unsignedTx,
239
237
  feePayerClient,
240
238
  enableFeePayer: feeData.enableFeePayer,
241
239
  })
242
240
 
243
- if (tx.txMeta.usedFeePayer) {
244
- tx.txMeta.fee = asset.feeAsset.currency.ZERO
245
- } else {
241
+ const fee = tx.txMeta.usedFeePayer ? asset.feeAsset.currency.ZERO : calculatedFee
242
+ tx.txMeta.fee = fee.toBaseNumber()
243
+
244
+ if (!tx.txMeta.usedFeePayer) {
246
245
  const rentExemptValue = await api.getRentExemptionMinAmount(toAddress)
247
246
  const rentExemptAmount = baseAsset.currency.baseUnit(rentExemptValue)
247
+ const senderRentExemptAmount = baseAsset.currency.baseUnit(
248
+ await api.getMinimumBalanceForRentExemption(0)
249
+ )
250
+
251
+ const baseAssetBalance = baseAsset.currency.baseUnit(await api.getBalance(fromAddress))
248
252
 
249
253
  // differentiate between SOL and Solana token
250
254
  let isEnoughForRent = false
251
255
  if (asset.name === baseAsset.name && !nft) {
252
256
  // sending SOL
253
- isEnoughForRent = amount.gte(rentExemptAmount)
257
+ const remaining = baseAssetBalance.sub(calculatedFee).sub(amount)
258
+ isEnoughForRent =
259
+ amount.gte(rentExemptAmount) && (remaining.isZero || remaining.gte(rentExemptAmount))
254
260
  } else {
255
261
  // sending token/nft
256
- const baseAssetBalance = await api.getBalance(fromAddress)
257
- isEnoughForRent = baseAsset.currency
258
- .baseUnit(baseAssetBalance)
259
- .sub(fee || asset.feeAsset.currency.ZERO)
260
- .gte(rentExemptAmount)
262
+ isEnoughForRent = baseAssetBalance.sub(calculatedFee).gte(senderRentExemptAmount)
261
263
  }
262
264
 
263
265
  if (!isEnoughForRent) {
@@ -267,7 +269,7 @@ export const createTxFactory = ({ assetClientInterface, api, feePayerClient }) =
267
269
  }
268
270
  }
269
271
 
270
- return tx
272
+ return { unsignedTx: tx, fee }
271
273
  }
272
274
  }
273
275
 
package/src/get-fees.js CHANGED
@@ -49,14 +49,14 @@ export const getFeeAsyncFactory = ({ createTx }) => {
49
49
  }
50
50
 
51
51
  try {
52
- unsignedTx = await createTx({
52
+ ;({ unsignedTx } = await createTx({
53
53
  asset,
54
54
  walletAccount,
55
55
  feeData,
56
56
  amount: amount ?? asset.currency.baseUnit(1),
57
57
  toAddress: toAddress ?? rest.fromAddress,
58
58
  ...rest,
59
- })
59
+ }))
60
60
  } catch (err) {
61
61
  console.log('error computing right SOL fee:', err)
62
62
  // simulating a tx will fail if the user has not enough balance
@@ -114,13 +114,17 @@ export class SolanaWebsocketMonitor extends SolanaClarityMonitor {
114
114
 
115
115
  // subscribe to new tokenAccounts
116
116
  for (const mintAddress of unknownTokensList) {
117
- await this.wsApi.accountSubscribe({ owner: address, account: mintAddress })
118
117
  const tokenName = this.api.tokens.get(mintAddress)?.name
119
118
  if (!tokenName) {
120
119
  console.log(`Unknown token mint address: ${mintAddress}`)
121
120
  continue
122
121
  }
123
122
 
123
+ const tokenAccountAddress = tokenAccounts.find(
124
+ (acc) => acc.mintAddress === mintAddress
125
+ )?.tokenAccountAddress
126
+ await this.wsApi.accountSubscribe({ owner: address, account: tokenAccountAddress })
127
+
124
128
  // update only token balances for known tokens
125
129
  const amount = splBalances[mintAddress]
126
130
  const newData = {
package/src/ws-api.js CHANGED
@@ -186,14 +186,12 @@ export class WsApi {
186
186
  const mappedTransactions = []
187
187
  for (const tx of transactions) {
188
188
  // we get the token name using the token.mintAddress
189
- let tokenName = tokens.get(tx.token?.mintAddress)?.name
190
- if (tx.token && !tokenName) {
191
- tokenName = 'unknown' // unknown token
192
- }
189
+ const tokenName = tokens.get(tx.token?.mintAddress)?.name
190
+ if (tx.token && !tokenName) continue // skip unknown tokens
193
191
 
194
192
  const assetName = tokenName ?? baseAsset.name
195
193
  const asset = assets[assetName]
196
- if (assetName === 'unknown' || !asset) return // skip unknown tokens
194
+ if (!asset) continue // asset not found
197
195
  const feeAsset = asset.feeAsset
198
196
 
199
197
  const coinAmount = tx.amount ? asset.currency.baseUnit(tx.amount) : asset.currency.ZERO