@exodus/solana-api 3.26.5 → 3.27.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
@@ -3,6 +3,26 @@
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.27.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.26.6...@exodus/solana-api@3.27.0) (2026-01-08)
7
+
8
+
9
+ ### Features
10
+
11
+
12
+ * feat: filter SOL poisoning txs (#7212)
13
+
14
+
15
+
16
+ ## [3.26.6](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.26.5...@exodus/solana-api@3.26.6) (2026-01-08)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+
22
+ * fix: Solana send-all leaving dust due to rent exemption check failure (#7217)
23
+
24
+
25
+
6
26
  ## [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
27
 
8
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/solana-api",
3
- "version": "3.26.5",
3
+ "version": "3.27.0",
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",
@@ -33,7 +33,7 @@
33
33
  "@exodus/fetch": "^1.7.3",
34
34
  "@exodus/models": "^12.0.1",
35
35
  "@exodus/simple-retry": "^0.0.6",
36
- "@exodus/solana-lib": "^3.17.0",
36
+ "@exodus/solana-lib": "^3.19.0",
37
37
  "@exodus/solana-meta": "^2.0.2",
38
38
  "@exodus/timer": "^1.1.1",
39
39
  "debug": "^4.1.1",
@@ -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": "1d62bfbf0924dc4c6eb52f6af2417c220f7454cb",
52
+ "gitHead": "273cd4583facb72bc145c5cdfe29063f78b13491",
53
53
  "bugs": {
54
54
  "url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Asolana-api"
55
55
  },
package/src/api.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  buildRawTransaction,
8
8
  computeBalance,
9
9
  deserializeMetaplexMetadata,
10
+ EXODUS_TRUSTED_SIGNERS,
10
11
  filterAccountsByOwner,
11
12
  getMetadataAccount,
12
13
  getTransactionSimulationParams,
@@ -232,6 +233,13 @@ export class Api {
232
233
  })
233
234
 
234
235
  if (!parsedTx.from && parsedTx.tokenTxs?.length === 0 && !includeUnparsed) return // cannot parse it
236
+ if (
237
+ !parsedTx.ownerIsFeePayer &&
238
+ parsedTx.error &&
239
+ !EXODUS_TRUSTED_SIGNERS.includes(parsedTx.feePayer)
240
+ ) {
241
+ return
242
+ } // skip address poisoning txs attempts.
235
243
 
236
244
  // split dexTx in separate txs
237
245
  if (parsedTx.dexTxs) {
@@ -242,8 +242,6 @@ export const createTxFactory = ({ assetClientInterface, api, feePayerClient }) =
242
242
  tx.txMeta.fee = fee.toBaseNumber()
243
243
 
244
244
  if (!tx.txMeta.usedFeePayer) {
245
- const rentExemptValue = await api.getRentExemptionMinAmount(toAddress)
246
- const rentExemptAmount = baseAsset.currency.baseUnit(rentExemptValue)
247
245
  const senderRentExemptAmount = baseAsset.currency.baseUnit(
248
246
  await api.getMinimumBalanceForRentExemption(0)
249
247
  )
@@ -254,7 +252,9 @@ export const createTxFactory = ({ assetClientInterface, api, feePayerClient }) =
254
252
  let isEnoughForRent = false
255
253
  if (asset.name === baseAsset.name && !nft) {
256
254
  // sending SOL
257
- const remaining = baseAssetBalance.sub(calculatedFee).sub(amount)
255
+ const rentExemptValue = await api.getRentExemptionMinAmount(toAddress)
256
+ const rentExemptAmount = baseAsset.currency.baseUnit(rentExemptValue)
257
+ const remaining = baseAssetBalance.sub(calculatedFee).sub(amount).clampLowerZero()
258
258
  isEnoughForRent =
259
259
  amount.gte(rentExemptAmount) && (remaining.isZero || remaining.gte(rentExemptAmount))
260
260
  } else {
package/src/tx-parser.js CHANGED
@@ -87,6 +87,8 @@ export const parseTransaction = (
87
87
  id: txId,
88
88
  slot: txDetails.slot,
89
89
  error: !(txDetails.meta.err === null),
90
+ ownerIsFeePayer,
91
+ feePayer: feePayerPubkey,
90
92
  owner,
91
93
  from,
92
94
  to,
@@ -219,6 +221,8 @@ export const parseTransaction = (
219
221
  program: ix.program,
220
222
  type: ix.parsed.type,
221
223
  slot: txDetails.slot,
224
+ ownerIsFeePayer,
225
+ feePayer: feePayerPubkey,
222
226
  owner: isSending ? ownerAddress : null,
223
227
  from: isSending ? ownerAddress : source,
224
228
  to: isSending ? destination : ownerAddress,
@@ -361,6 +365,8 @@ export const parseTransaction = (
361
365
  id: txId,
362
366
  slot: txDetails.slot,
363
367
  error: !(txDetails.meta.err === null),
368
+ ownerIsFeePayer,
369
+ feePayer: feePayerPubkey,
364
370
  ...tx,
365
371
  }))
366
372
  } else if (preTokenBalances && postTokenBalances) {
@@ -428,6 +434,8 @@ export const parseTransaction = (
428
434
  id: txId,
429
435
  slot: txDetails.slot,
430
436
  error: !(txDetails.meta.err === null),
437
+ ownerIsFeePayer,
438
+ feePayer: feePayerPubkey,
431
439
  ...tx,
432
440
  }
433
441
  }
package/src/ws-api.js CHANGED
@@ -1,4 +1,11 @@
1
- import { PublicKey, Token, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, U64 } from '@exodus/solana-lib'
1
+ import {
2
+ EXODUS_TRUSTED_SIGNERS,
3
+ PublicKey,
4
+ Token,
5
+ TOKEN_2022_PROGRAM_ID,
6
+ TOKEN_PROGRAM_ID,
7
+ U64,
8
+ } from '@exodus/solana-lib'
2
9
  import lodash from 'lodash'
3
10
 
4
11
  import { Connection } from './connection.js'
@@ -150,6 +157,13 @@ export class WsApi {
150
157
  const timestamp = Date.now() // the notification event has no blockTime
151
158
 
152
159
  if (!parsedTx.from && parsedTx.tokenTxs?.length === 0) return { logItemsByAsset: {} } // cannot parse it
160
+ if (
161
+ !parsedTx.ownerIsFeePayer &&
162
+ parsedTx.error &&
163
+ !EXODUS_TRUSTED_SIGNERS.includes(parsedTx.feePayer)
164
+ ) {
165
+ return { logItemsByAsset: {} } // skip address poisoning txs attempts.
166
+ }
153
167
 
154
168
  const transactions = [] // because one single tx can have multiple instructions inside
155
169