@exodus/solana-api 3.17.4 → 3.18.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 CHANGED
@@ -3,6 +3,32 @@
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.18.1](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.18.0...@exodus/solana-api@3.18.1) (2025-05-05)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix: SOL reserve and units consumed (#5540)
13
+
14
+
15
+
16
+ ## [3.18.0](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.17.4...@exodus/solana-api@3.18.0) (2025-05-01)
17
+
18
+
19
+ ### Features
20
+
21
+
22
+ * feat(solana): make shouldUpdateBalanceBeforeHistory configurable (#5544)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+
28
+ * fix: SOL staking regression (#5539)
29
+
30
+
31
+
6
32
  ## [3.17.4](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.17.3...@exodus/solana-api@3.17.4) (2025-04-25)
7
33
 
8
34
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/solana-api",
3
- "version": "3.17.4",
3
+ "version": "3.18.1",
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",
@@ -47,7 +47,7 @@
47
47
  "@exodus/assets-testing": "^1.0.0",
48
48
  "@exodus/solana-web3.js": "^1.63.1-exodus.9-rc3"
49
49
  },
50
- "gitHead": "aaa9d5613e770483159c799b5ccf5bef971acc47",
50
+ "gitHead": "e277f0baf182bfc4af6a5f9e66c92ff88288a9ef",
51
51
  "bugs": {
52
52
  "url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Asolana-api"
53
53
  },
@@ -30,6 +30,7 @@ export const createUnsignedTxForSend = async ({
30
30
  // staking
31
31
  method,
32
32
  stakeAddresses,
33
+ accounts,
33
34
  seed,
34
35
  pool,
35
36
  // <MagicEden>
@@ -119,6 +120,7 @@ export const createUnsignedTxForSend = async ({
119
120
  const stakingParams = {
120
121
  method,
121
122
  stakeAddresses,
123
+ accounts,
122
124
  seed,
123
125
  pool,
124
126
  }
@@ -173,8 +175,10 @@ export const createUnsignedTxForSend = async ({
173
175
  message,
174
176
  })
175
177
  if (err) {
176
- // we don't throw error here, because we can use this method to estimate fee
177
- console.log('SOL estimate unitsConsumed err:', JSON.stringify(err))
178
+ // we use this method to compute unitsConsumed
179
+ // we can throw error here and fallback to ~0.02 SOL or estimate fee based on the method
180
+ console.log('error getting units consumed:', err)
181
+ throw new Error(err)
178
182
  }
179
183
 
180
184
  return unitsConsumed + CU_FOR_COMPUTE_BUDGET_INSTRUCTIONS
package/src/get-fees.js CHANGED
@@ -3,7 +3,7 @@ import assert from 'minimalistic-assert'
3
3
 
4
4
  import { createUnsignedTxForSend } from './create-unsigned-tx-for-send.js'
5
5
 
6
- const DEFAULT_RESERVE_FEE = '0.01' // SOL
6
+ const DEFAULT_SAFE_FEE = '0.0025' // SOL (enough for rent exemption)
7
7
 
8
8
  export const getFeeAsyncFactory = ({ api }) => {
9
9
  assert(api, 'api is required')
@@ -37,16 +37,18 @@ export const getFeeAsyncFactory = ({ api }) => {
37
37
  for (const [addr, info] of Object.entries(stakingInfo.accounts || {})) {
38
38
  if (method === 'undelegate' && (info.state === 'active' || info.state === 'activating'))
39
39
  stakeAddresses.push(addr)
40
- if (method === 'withdraw' && info.state === 'inactive') stakeAddresses.push(addr)
41
40
  }
42
41
 
43
42
  rest.stakeAddresses = stakeAddresses
43
+ rest.accounts = stakingInfo.accounts
44
+
44
45
  amount =
45
46
  method === 'undelegate'
46
47
  ? stakingInfo.locked // unstake all
47
48
  : method === 'withdraw'
48
49
  ? stakingInfo.withdrawable // withdraw all
49
50
  : amount
51
+ // withdraw won't use amount, will extract it from accounts
50
52
  }
51
53
 
52
54
  try {
@@ -64,7 +66,8 @@ export const getFeeAsyncFactory = ({ api }) => {
64
66
  } catch (err) {
65
67
  console.log('error computing right SOL fee:', err)
66
68
  // simulating a tx will fail if the user has not enough balance
67
- fee = asset.feeAsset.currency.defaultUnit(DEFAULT_RESERVE_FEE)
69
+ // we fallback to a default fee (but we could leave some dust)
70
+ fee = asset.feeAsset.currency.defaultUnit(DEFAULT_SAFE_FEE)
68
71
  }
69
72
  }
70
73
 
package/src/index.js CHANGED
@@ -6,7 +6,7 @@ import { Api } from './api.js'
6
6
 
7
7
  export { SolanaMonitor } from './tx-log/index.js'
8
8
  export { createAccountState } from './account-state.js'
9
- export { getSolStakedFee, getStakingInfo } from './staking-utils.js'
9
+ export { getStakingInfo } from './staking-utils.js'
10
10
  export {
11
11
  isSolanaStaking,
12
12
  isSolanaUnstaking,
@@ -1,20 +1,3 @@
1
- /**
2
- * Generates pending Fee for stake-able asset
3
- * @param {Object} stakingInfo solana staking information object
4
- * @param {Object} fee solana asset fee
5
- *
6
- */
7
- export const getSolStakedFee = ({ asset, stakingInfo, fee }) => {
8
- const { currency } = asset
9
- const { accounts } = stakingInfo
10
-
11
- // TODO: REMOVE this method.. only used in Desktop!
12
- // (also this is wrong, accounts must be filtered by state to compute the right fee)
13
-
14
- const allPending = Object.entries(accounts).length
15
- return allPending > 0 ? fee.mul(allPending) : currency.ZERO
16
- }
17
-
18
1
  export const getStakingInfo = (stakingInfo) => {
19
2
  return {
20
3
  loaded: stakingInfo.loaded,
@@ -23,6 +23,7 @@ export class SolanaMonitor extends BaseMonitor {
23
23
  ticksBetweenHistoryFetches = TICKS_BETWEEN_HISTORY_FETCHES,
24
24
  ticksBetweenStakeFetches = TICKS_BETWEEN_STAKE_FETCHES,
25
25
  txsLimit,
26
+ shouldUpdateBalanceBeforeHistory = true,
26
27
  ...args
27
28
  }) {
28
29
  super(args)
@@ -33,6 +34,7 @@ export class SolanaMonitor extends BaseMonitor {
33
34
  this.staking = DEFAULT_REMOTE_CONFIG.staking
34
35
  this.ticksBetweenStakeFetches = ticksBetweenStakeFetches
35
36
  this.ticksBetweenHistoryFetches = ticksBetweenHistoryFetches
37
+ this.shouldUpdateBalanceBeforeHistory = shouldUpdateBalanceBeforeHistory
36
38
  this.includeUnparsed = includeUnparsed
37
39
  this.txsLimit = txsLimit
38
40
  this.addHook('before-stop', (...args) => this.beforeStop(...args))
@@ -167,10 +169,9 @@ export class SolanaMonitor extends BaseMonitor {
167
169
 
168
170
  const shouldUpdateHistory = refresh || isHistoryUpdateTick || balanceChanged
169
171
  const shouldUpdateOnlyBalance = balanceChanged && !shouldUpdateHistory
170
- const shouldUpdateBalanceBeforeHistory = true
171
172
 
172
173
  // getHistory is more likely to fail/be rate limited, so we want to update users balance only on a lot of ticks
173
- if (shouldUpdateBalanceBeforeHistory || shouldUpdateOnlyBalance) {
174
+ if (this.shouldUpdateBalanceBeforeHistory || shouldUpdateOnlyBalance) {
174
175
  // update all state at once
175
176
  await this.updateState({ account, walletAccount, staking })
176
177
  await this.emitUnknownTokensEvent({ tokenAccounts })
package/src/tx-send.js CHANGED
@@ -69,8 +69,7 @@ export const createAndBroadcastTXFactory =
69
69
  let data
70
70
  if (isStakingTx) {
71
71
  data = {
72
- ...txLogData.stakingParams,
73
- stake: coinAmount.toBaseNumber(),
72
+ staking: { ...txLogData.stakingParams, stake: coinAmount.toBaseNumber() },
74
73
  }
75
74
  } else {
76
75
  data = Object.create(null)