@exodus/solana-api 3.27.5 → 3.27.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 +12 -0
- package/package.json +2 -2
- package/src/connection.js +3 -3
- package/src/tx-log/clarity-monitor.js +2 -1
- package/src/tx-log/merge-transactions.js +40 -0
- package/src/tx-log/solana-monitor.js +2 -1
- package/src/ws-api.js +2 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
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.6](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.27.5...@exodus/solana-api@3.27.6) (2026-01-21)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
* fix: improve SOL WS events logging (#7293)
|
|
13
|
+
|
|
14
|
+
* fix: Solana merge multi-transfer transactions to prevent data loss (#7297)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
6
18
|
## [3.27.5](https://github.com/ExodusMovement/assets/compare/@exodus/solana-api@3.27.4...@exodus/solana-api@3.27.5) (2026-01-19)
|
|
7
19
|
|
|
8
20
|
**Note:** Version bump only for package @exodus/solana-api
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@exodus/solana-api",
|
|
3
|
-
"version": "3.27.
|
|
3
|
+
"version": "3.27.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",
|
|
@@ -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": "
|
|
52
|
+
"gitHead": "9bc961015aa41912a6cbcfde9ef98e090fe39b41",
|
|
53
53
|
"bugs": {
|
|
54
54
|
"url": "https://github.com/ExodusMovement/assets/issues?q=is%3Aissue+is%3Aopen+label%3Asolana-api"
|
|
55
55
|
},
|
package/src/connection.js
CHANGED
|
@@ -118,7 +118,7 @@ export class Connection {
|
|
|
118
118
|
this.onMsg(json)
|
|
119
119
|
} catch (e) {
|
|
120
120
|
debug(e)
|
|
121
|
-
debug('Cannot process msg:', evt
|
|
121
|
+
debug('Cannot process msg:', evt)
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
@@ -135,11 +135,11 @@ export class Connection {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
onError(evt) {
|
|
138
|
-
debug('Error on WS:', evt
|
|
138
|
+
debug('Error on WS:', evt)
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
onClose(evt) {
|
|
142
|
-
debug('Closing WS')
|
|
142
|
+
debug('Closing WS', evt)
|
|
143
143
|
clearInterval(this.pingTimeout)
|
|
144
144
|
clearTimeout(this.reconnectTimeout)
|
|
145
145
|
this.onConnectionClose(evt)
|
|
@@ -5,6 +5,7 @@ import assert from 'minimalistic-assert'
|
|
|
5
5
|
import ms from 'ms'
|
|
6
6
|
|
|
7
7
|
import { DEFAULT_POOL_ADDRESS } from '../account-state.js'
|
|
8
|
+
import { mergeByTxId } from './merge-transactions.js'
|
|
8
9
|
|
|
9
10
|
const DEFAULT_REMOTE_CONFIG = {
|
|
10
11
|
clarityUrl: [],
|
|
@@ -261,7 +262,7 @@ export class SolanaClarityMonitor extends BaseMonitor {
|
|
|
261
262
|
mappedTransactions.push(item)
|
|
262
263
|
}
|
|
263
264
|
|
|
264
|
-
const logItemsByAsset = lodash.groupBy(mappedTransactions,
|
|
265
|
+
const logItemsByAsset = lodash.groupBy(mergeByTxId(mappedTransactions), 'coinName')
|
|
265
266
|
return {
|
|
266
267
|
logItemsByAsset,
|
|
267
268
|
hasNewTxs: transactions.length > 0,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import lodash from 'lodash'
|
|
2
|
+
|
|
3
|
+
const { groupBy, uniq } = lodash
|
|
4
|
+
|
|
5
|
+
// Merge multiple transfers of the same token within one transaction (e.g., Jupiter swaps)
|
|
6
|
+
export function mergeByTxId(transactions) {
|
|
7
|
+
const grouped = groupBy(transactions, (tx) => `${tx.txId}:${tx.coinName}`)
|
|
8
|
+
|
|
9
|
+
return Object.values(grouped).map((group) => {
|
|
10
|
+
if (group.length === 1) return group[0]
|
|
11
|
+
|
|
12
|
+
const base = group[0]
|
|
13
|
+
const currency = base.currencies[base.coinName]
|
|
14
|
+
const totalAmount = group.reduce((sum, tx) => sum.add(tx.coinAmount), currency.ZERO)
|
|
15
|
+
|
|
16
|
+
if (base.coinAmount.isPositive) {
|
|
17
|
+
return {
|
|
18
|
+
...base,
|
|
19
|
+
coinAmount: totalAmount,
|
|
20
|
+
from: uniq(group.flatMap((tx) => tx.from)),
|
|
21
|
+
data: {
|
|
22
|
+
...base.data,
|
|
23
|
+
received: group.map((tx) => ({
|
|
24
|
+
address: tx.from[0],
|
|
25
|
+
amount: tx.coinAmount.toDefaultString({ unit: true }),
|
|
26
|
+
})),
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
...base,
|
|
33
|
+
coinAmount: totalAmount,
|
|
34
|
+
data: {
|
|
35
|
+
...base.data,
|
|
36
|
+
sent: group.flatMap((tx) => tx.data?.sent || []),
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
}
|
|
@@ -4,6 +4,7 @@ import assert from 'minimalistic-assert'
|
|
|
4
4
|
import ms from 'ms'
|
|
5
5
|
|
|
6
6
|
import { DEFAULT_POOL_ADDRESS } from '../account-state.js'
|
|
7
|
+
import { mergeByTxId } from './merge-transactions.js'
|
|
7
8
|
|
|
8
9
|
const DEFAULT_REMOTE_CONFIG = {
|
|
9
10
|
rpcs: [],
|
|
@@ -244,7 +245,7 @@ export class SolanaMonitor extends BaseMonitor {
|
|
|
244
245
|
mappedTransactions.push(item)
|
|
245
246
|
}
|
|
246
247
|
|
|
247
|
-
const logItemsByAsset = _.groupBy(mappedTransactions,
|
|
248
|
+
const logItemsByAsset = _.groupBy(mergeByTxId(mappedTransactions), 'coinName')
|
|
248
249
|
return {
|
|
249
250
|
logItemsByAsset,
|
|
250
251
|
hasNewTxs: transactions.length > 0,
|
package/src/ws-api.js
CHANGED
|
@@ -2,6 +2,7 @@ import { PublicKey, Token, TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, U64 } from '
|
|
|
2
2
|
import lodash from 'lodash'
|
|
3
3
|
|
|
4
4
|
import { Connection } from './connection.js'
|
|
5
|
+
import { mergeByTxId } from './tx-log/merge-transactions.js'
|
|
5
6
|
import { parseTransaction } from './tx-parser.js'
|
|
6
7
|
import { isSolAddressPoisoningTx } from './txs-utils.js'
|
|
7
8
|
|
|
@@ -262,7 +263,7 @@ export class WsApi {
|
|
|
262
263
|
mappedTransactions.push(item)
|
|
263
264
|
}
|
|
264
265
|
|
|
265
|
-
const logItemsByAsset = lodash.groupBy(mappedTransactions,
|
|
266
|
+
const logItemsByAsset = lodash.groupBy(mergeByTxId(mappedTransactions), 'coinName')
|
|
266
267
|
return {
|
|
267
268
|
logItemsByAsset,
|
|
268
269
|
cursorState: transactions[0]?.id ? { cursor: transactions[0].id } : {},
|