@exodus/solana-api 3.20.4 → 3.20.6

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.20.6](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.20.5...@exodus/solana-api@3.20.6) (2025-07-18)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+
12
+ * fix: SOL parse mint transaction (#6045)
13
+
14
+
15
+
16
+ ## [3.20.5](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.20.4...@exodus/solana-api@3.20.5) (2025-07-11)
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+
22
+ * fix: catch SOL rewards endpoint error (#6055)
23
+
24
+
25
+
6
26
  ## [3.20.4](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.20.3...@exodus/solana-api@3.20.4) (2025-07-01)
7
27
 
8
28
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exodus/solana-api",
3
- "version": "3.20.4",
3
+ "version": "3.20.6",
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",
@@ -46,7 +46,7 @@
46
46
  "@exodus/assets-testing": "^1.0.0",
47
47
  "@exodus/solana-web3.js": "^1.63.1-exodus.9-rc3"
48
48
  },
49
- "gitHead": "3ce3cad33597f430b7c215fced6d19344fc05c69",
49
+ "gitHead": "a7ce3c50e11f41e17cdf980d9ec0756c756beb93",
50
50
  "bugs": {
51
51
  "url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Asolana-api"
52
52
  },
package/src/api.js CHANGED
@@ -22,7 +22,11 @@ import urljoin from 'url-join'
22
22
 
23
23
  import { Connection } from './connection.js'
24
24
  import { getStakeActivation } from './get-stake-activation/index.js'
25
- import { isSolTransferInstruction, isSplTransferInstruction } from './txs-utils.js'
25
+ import {
26
+ isSolTransferInstruction,
27
+ isSplMintInstruction,
28
+ isSplTransferInstruction,
29
+ } from './txs-utils.js'
26
30
 
27
31
  const createApi = createApiCJS.default || createApiCJS
28
32
 
@@ -473,12 +477,15 @@ export class Api {
473
477
  (ix) =>
474
478
  ix.parsed &&
475
479
  (isSplTransferInstruction({ program: ix.program, type: ix.parsed.type }) ||
480
+ isSplMintInstruction({ program: ix.program, type: ix.parsed.type }) ||
476
481
  (!includeUnparsed &&
477
482
  isSolTransferInstruction({ program: ix.program, type: ix.parsed.type })))
478
483
  )
479
484
  .map((ix) => {
480
- const source = lodash.get(ix, 'parsed.info.source')
481
- const destination = lodash.get(ix, 'parsed.info.destination')
485
+ let source = lodash.get(ix, 'parsed.info.source')
486
+ const destination = isSplMintInstruction({ program: ix.program, type: ix.parsed.type })
487
+ ? lodash.get(ix, 'parsed.info.account') // only for minting
488
+ : lodash.get(ix, 'parsed.info.destination')
482
489
  const amount = Number(
483
490
  lodash.get(ix, 'parsed.info.amount', 0) ||
484
491
  lodash.get(ix, 'parsed.info.tokenAmount.amount', 0)
@@ -545,6 +552,10 @@ export class Api {
545
552
  })
546
553
  if (!tokenAccount) return
547
554
 
555
+ if (isSplMintInstruction({ program: ix.program, type: ix.parsed.type })) {
556
+ source = lodash.get(ix, 'parsed.info.mintAuthority')
557
+ }
558
+
548
559
  const isSending = tokenAccountsByOwner.some(({ tokenAccountAddress }) => {
549
560
  return [source].includes(tokenAccountAddress)
550
561
  })
@@ -552,6 +563,8 @@ export class Api {
552
563
  // owner if it's a send tx
553
564
  return {
554
565
  id: txId,
566
+ program: ix.program,
567
+ type: ix.parsed.type,
555
568
  slot: txDetails.slot,
556
569
  owner: isSending ? ownerAddress : null,
557
570
  from: isSending ? ownerAddress : source,
@@ -679,6 +692,7 @@ export class Api {
679
692
  // Parse Token txs
680
693
  const tokenTxs = this._parseTokenTransfers({
681
694
  instructions,
695
+ innerInstructions,
682
696
  tokenAccountsByOwner,
683
697
  ownerAddress,
684
698
  fee,
@@ -769,6 +783,7 @@ export class Api {
769
783
 
770
784
  _parseTokenTransfers({
771
785
  instructions,
786
+ innerInstructions = [],
772
787
  tokenAccountsByOwner,
773
788
  ownerAddress,
774
789
  fee,
@@ -829,6 +844,36 @@ export class Api {
829
844
  }
830
845
  })
831
846
 
847
+ innerInstructions.forEach((parsedIx) => {
848
+ const { type, program, amount, from, to } = parsedIx
849
+
850
+ // Handle token minting (mintTo, mintToChecked)
851
+ if (isSplMintInstruction({ program, type })) {
852
+ const {
853
+ token: { tokenAccountAddress },
854
+ } = parsedIx
855
+
856
+ // Check if the destination token account belongs to our owner
857
+ const tokenAccount = lodash.find(tokenAccountsByOwner, {
858
+ tokenAccountAddress,
859
+ })
860
+
861
+ if (!tokenAccount) return // not our token account
862
+
863
+ delete tokenAccount.balance
864
+ delete tokenAccount.owner
865
+
866
+ tokenTxs.push({
867
+ owner: null, // no owner for minting (it's created from thin air)
868
+ token: tokenAccount,
869
+ from, // mint address as the source
870
+ to, // our address as recipient
871
+ amount: Number(amount || 0),
872
+ fee: 0, // no fee for receiving minted tokens
873
+ })
874
+ }
875
+ })
876
+
832
877
  return tokenTxs
833
878
  }
834
879
 
@@ -325,7 +325,7 @@ export class SolanaMonitor extends BaseMonitor {
325
325
 
326
326
  const staking =
327
327
  this.isStakingEnabled() && fetchStakingInfo
328
- ? await this.getStakingInfo({ address, walletAccount })
328
+ ? await this.getStakingInfo({ address, accountState, walletAccount })
329
329
  : { ...accountState.stakingInfo, staking: this.staking }
330
330
 
331
331
  const stakedBalance = this.asset.currency.baseUnit(staking.locked)
@@ -366,9 +366,15 @@ export class SolanaMonitor extends BaseMonitor {
366
366
  return this.updateAccountState({ newData, walletAccount })
367
367
  }
368
368
 
369
- async getStakingInfo({ address, walletAccount }) {
369
+ async getStakingInfo({ address, accountState, walletAccount }) {
370
370
  const stakingInfo = await this.api.getStakeAccountsInfo(address)
371
- const rewards = await this.api.getRewards(address)
371
+ let earned = accountState.stakingInfo.earned.toBaseString()
372
+ try {
373
+ const rewards = await this.api.getRewards(address)
374
+ earned = rewards
375
+ } catch (error) {
376
+ console.warn(error)
377
+ }
372
378
 
373
379
  return {
374
380
  loaded: true,
@@ -380,7 +386,7 @@ export class SolanaMonitor extends BaseMonitor {
380
386
  activating: this.asset.currency.baseUnit(stakingInfo.activating),
381
387
  withdrawable: this.asset.currency.baseUnit(stakingInfo.withdrawable),
382
388
  pending: this.asset.currency.baseUnit(stakingInfo.pending), // still undelegating (not yet available for withdraw)
383
- earned: this.asset.currency.baseUnit(rewards),
389
+ earned: this.asset.currency.baseUnit(earned),
384
390
  accounts: stakingInfo.accounts, // Obj
385
391
  }
386
392
  }
package/src/txs-utils.js CHANGED
@@ -4,6 +4,8 @@ const TRANSFER_INSTRUCTION_TYPES = new Set([
4
4
  'transferCheckedWithFee',
5
5
  ])
6
6
 
7
+ const MINT_INSTRUCTION_TYPES = new Set(['mintTo', 'mintToChecked'])
8
+
7
9
  const isSolanaTx = (tx) => tx.coinName === 'solana'
8
10
  export const isSolanaStaking = (tx) =>
9
11
  isSolanaTx(tx) && ['createAccountWithSeed', 'delegate'].includes(tx?.data?.staking?.method)
@@ -18,3 +20,6 @@ export const isSplTransferInstruction = ({ program, type }) =>
18
20
 
19
21
  export const isSolTransferInstruction = ({ program, type }) =>
20
22
  program === 'system' && TRANSFER_INSTRUCTION_TYPES.has(type)
23
+
24
+ export const isSplMintInstruction = ({ program, type }) =>
25
+ program === 'spl-token' && MINT_INSTRUCTION_TYPES.has(type)